经常用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
05-01 05:07