【发布时间】:2018-07-13 18:07:48
【问题描述】:
我是 x86_64 汇编编程的新手。我正在用 x86_64 程序集编写简单的“Hello World”程序。下面是我的代码,运行良好。
global _start
section .data
msg: db "Hello to the world of SLAE64", 0x0a
mlen equ $-msg
section .text
_start:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, mlen
syscall
mov rax, 60
mov rdi, 4
syscall
现在当我在 gdb 中反汇编时,它会给出以下输出:
(gdb) disas
Dump of assembler code for function _start:
=> 0x00000000004000b0 <+0>: mov eax,0x1
0x00000000004000b5 <+5>: mov edi,0x1
0x00000000004000ba <+10>: movabs rsi,0x6000d8
0x00000000004000c4 <+20>: mov edx,0x1d
0x00000000004000c9 <+25>: syscall
0x00000000004000cb <+27>: mov eax,0x3c
0x00000000004000d0 <+32>: mov edi,0x4
0x00000000004000d5 <+37>: syscall
End of assembler dump.
我的问题是为什么 NASM 会这样?我知道它会根据操作码更改指令,但我不确定寄存器是否有相同的行为。
这种行为也会影响可执行文件的功能吗?
我正在使用 i5 处理器上安装在 VMware 中的 Ubuntu 16.04(64 位)。
提前谢谢你。
【问题讨论】:
-
它的尺寸优化。
mov rax,1与mov eax,1具有完全相同的效果(因为在 x86-64 上写入像eax这样的 32 位寄存器变体会自动清除 64 位rax的高 32 位,这就是 AMD 设计 x86-64 的方式)。而eax变体是微小立即数的 1B 短操作码(rax具有完全相同的操作码,前面有 REX 前缀字节)。 - 但即使在这种情况下我也不认为它会这样做,让我有点惊讶(我只知道mov eax,1自动选择imm8操作码变体,除非你写mov eax, dword 1来强制它使用@ 987654332@一)。 -
只是评论(不回答),因为我懒得检查是否有欺骗性。
-
@Ped7g:严格来说,这不是重复的 AFAIK;其他问题从不同的方向出现在同一个问题上,但我不记得看到有人问为什么 NASM 这样做。 (不过,我也没有搜索,因为这是一个足够好的问题,我并没有寻找关闭它的方法)
-
@Ped7g:“我只知道
mov eax,1自动选择imm8操作码变体” - 实际上没有mov的8 位扩展立即数形式,你错了。
标签: assembly nasm x86-64 micro-optimization shellcode