Linux汇编语言及嵌入式汇编(转载)

Linux汇编语言及嵌入式汇编(转载)  


汇编语言的优点是速度快,可以直接对硬件进行操作。Linux是用C语言开发的操作系统,可以在Linux中直接使用汇编这一底层语言来优化程序的性能。
汇编语言虽然运用不像高级语言那么广泛,但是却很重要。特别是在一些执行速度要求很高的场合,如Linux这样的操作系统。Linux中引导程序、启动程序及内核程序中都有很多汇编程序或嵌入式汇编程序。
汇编语言具有如下优点:
能够直接访问与硬件相关的存储器和I/O端口
不受编译器限制,对生成的二进制代码进行完全控制
能够对关键代码进行控制,避免因线程共同范围或硬件设备共享引起的死锁
对代码进行优化,提高执行速度
同时,汇编语言也有不容忽视的缺点:
代码难懂,不易维护
 
容易产生bug,调试困难
只能针对特定的体系结构和处理器进行优化
 开放效率低,周期长
Linux下用汇编语言编写的代码有两种形式:一种是完全的汇编代码,另外一种是内嵌的汇编代码,即可以内嵌到C语言的汇编代码片段,这主要依赖于编译器在这方面的扩展。
 
Linux汇编语言格式
不同于DOS/Windows下的Intel风格的汇编语言,Unix/Linux下的汇编语法风格主要是AT&T模式的。
1.        在AT&T汇编格式中,寄存器名前要加上“%”作为前缀。

AT&T格式

Intel格式

push %eax

push eax

2.        在AT&T汇编格式中,用‘$’前缀表示一个立即操作数;在Intel汇编格式中,立即数的表示不用带任何前缀。

AT&T格式

Intel格式

pushl $1

push 1

3.        AT&T和Intel格式中的源操作数和目的操作数的位置恰好相反。在Intel格式中,目的操作数在左边;而在AT&T格式中,目的操作数在右边。

AT&T格式

Intel格式

addl $1, %eax

add eax, 1

4.        在AT&T格式中,操作数的长度由操作符的最后一个字母决定,后缀‘b’,‘w’,‘l’分别表示操作数为字节(byte, 8bits),字(word, 16bits)和长字(long, 32bits);而在Intel格式中,操作数的字长由“byte ptr”和“word ptr”等前缀来表示。

AT&T格式

Intel格式

movb val, %al

mov al, byte ptr val

 
1.        在AT&T汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上‘*’
最为前缀,而在Intel格式中则不需要。
2.        远程转移指令和远程子调用指令的操作码,在AT&T汇编格式中为‘ljump’和‘lcall’;而在Intel汇编格式中为‘jmp far’和‘call far’


AT&T格式

Intel格式

ljump $section, $offset

jmp far section:offset

lcall $section, $offset

call far section:offset

   与之对应的远程返回指令为:

AT&T格式

Intel格式

lret $stack_adjust

ret far stack_adjust

3.        在AT&T汇编格式中,内存操作数的寻址方式是

section:disp(base, index, scale)
 
 而在Intel汇编格式中,内存操作数的寻址方式是:

 


section:[base + index* scale + disp]
 
 
由于Linux工作在保护模式下,用的是32位线性地址,所以在计算地址时不用考虑段基址和偏移量,采用如下的计算方法:

 


disp + base + index * scale
           
 
下面是一些内存操作数的例子:

AT&T格式

Intel格式

movl –4(%ebp), %eax

mov eax, [ebp-4]

movl array(,%eax, 4), %eax

mov eax,[eax*4 + array]

movw array(%ebx, %eax, 4), %cx

mov cx,[ebx + 4*eax + array]

movb $4, %fs:(%eax)

mov fs:eax, 4

 
Hello World!
Linux下有很多方法用于在屏幕上显示一个字符串,但最简洁的方式是使用Linux内核提供的系统调用。这种方法可以直接和操作系统内核进行通讯,不需要链接如libc这样的函数库,也不需要ELF解释器。Linux是一个运行于保护模式下的32位操作系统,采用平坦内存模式,最常用到的ELF二进制代码格式包含.text, .data和.bss等section。其中.text为只读代码区,.data为可读可写的数据区,而.bss为可读可写且没有初始化的数据区。一个ELF可执行程序最少应该包含.text部分。

AT&T格式的Hello, World


#hello.s
.data                                #数据段声明
msg : .string “hello, world!”        #要输出的字符串
len = . – msg                     #字符串长度
.text                                #代码段声明
.global _start                         #指定入口函数
_start:
movl $len, %edx                 
movl $msg, %ecx
movl $1, %ebx                   #文件描述符stdout
movl $4, %eax                   #系统调用号(sys_write)
int $0x80     

你可能感兴趣的:(Linux汇编语言及嵌入式汇编(转载))