2.1.3 GCC:AT&T 语法
我们来看一看在AT&T当中的汇编语法,这个语法在UNIX当中更普遍。
gcc -S 1_1.c
我们将得到这个:
.file "1_1.c"
.section .rodata
.LC0:
.string "hello, world"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call printf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3"
.section .note.GNU-stack, "", @progbits
有很多的宏(用点开始)。现在为了简单起见,我们先不看这些。(除了 .string ,就像一个C字符串编码一个null结尾的字符序列)。然后,我们将看到这个:
.LC0:
.string "hello, world"
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call printf
movl $0, %eax
leave
ret
在Intel与AT&T语法当中比较重要的区别就是:
操作数写在后面
在Intel语法中:<instruction> <destination operand> <source operand>
在AT&T语法中:<instruction> <source operand> <destination operand>
有一个理解它们的方法: 当你面对intel语法的时候,你可以想象把等号放到2个操作数中间,当面对AT&T语法的时候,你可以放一个右箭头(→)到两个操作数之间。
AT&T: 在寄存器名之前需要写一个百分号(%)并且在数字前面需要美元符($)。方括号被圆括号替代。 AT&T: 一些用来表示数据形式的特殊的符号
l long(32 bits)
w word(16bits)
b byte(8 bits)
让我们回到上面的编译结果:它和在IDA里看到的是一样的。只有一点不同:0FFFFFFF0h 被写成了$-16,但这是一样的,10进制的16在16进制里表示为0x10。-0x10就等同于0xFFFFFFF0(这是针对于32位构架)。
外加返回值这里用的MOV来设定为0,而不是用XOR。MOV仅仅是加载(load)了变量到寄存器。指令的名称并不直观。在其他的构架上,这条指令会被称作例如”load”这样的。
当前内容版权归 beginners.re 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 beginners.re .