经常用msam或tasm的童鞋一下转换到nasm下可能觉得不怎么适应,它们应该先去晓习一下gas的语法,然后就适应了…that‘s only a joke! :)
section .data
v101 dq 0x1234567811223344
;代码中有
mov rdx,[v101]
mov [rax*2],rdx
看一下生成的机器指令:
0x4000b0 <_start>: 0x4000ba <_start+10>: mov 0x600170,%rdx
0x4000c2 <_start+18>: mov %rdx,(%rax,%rax,1)
有2个地方有“惊奇”,首先机器码生产的貌似是将一个常量赋给rdx寄存器,实际上该常量是一个地址,是将该地址的内容赋给rdx,这从机器码上是一个容易混淆的地方;如果你要将地址的值赋给rdx,就可以看到生成的机器码会有不同,在整形数前有一个$,而且mov变为movabs:
mov rdx,v101
0x4000b0 <_start>: movabs $0x600170,%rdx
注意nasm操作数的顺序是intel样式的:从右到左,而gdb默认是at&t样式的:从左到右.你可用:
//默认是att
set disassembly-flavor intel
来改变为intel语法。
其次代码中需要生成的是[eax*2]的相对寻址,结果机器码是[eax+eax],这是编译器有意而为之的:为了省略偏移而节省空间。你可以增加NOSPLIT关键字改变这种行为:
mov [nosplit rax*2],rdx
生成的机器码为:
//原来的机器码为:QWORD PTR [rax+rax*1],rdx
//没有偏移域
mov QWORD PTR [rax*2+0x0],rdx