我刚开始用x86汇编,并试图一些基本MOV指令。 (下面的代码)
BITS 32
SECTION .data
somedata: db "Hello world",10
SECTION .text
global _start
_start:
mov eax, somedata
mov al, [eax]
mov edx, [somedata]
我似乎为什么NASM用相对RIP寻址,当指定它在装配BITS 32不明白(我想仅在64位模式下的相对寻址)。此外,它是在32位模式下使用RAX。如果我不指定任何东西,它似乎不使用相对寻址和使用EAX。
用BITS 32码
Disassembly of section .text:
00000000004000b0 <_start>:
4000b0: b8 c0 00 60 00 mov eax,0x6000c0
4000b5: 8a 00 mov al,BYTE PTR [rax]
4000b7: 8b 15 c0 00 60 00 mov edx,DWORD PTR [rip+0x6000c0] # a0017d <_end+0x4000ad>
无码32 BITS
Disassembly of section .text:
00000000004000b0 <_start>:
4000b0: b8 c0 00 60 00 mov eax,0x6000c0
4000b5: 67 8a 00 mov al,BYTE PTR [eax]
4000b8: 8b 14 25 c0 00 60 00 mov edx,DWORD PTR ds:0x6000c0
我知道这是不是汇编,这是我的。它是什么,我做错了什么?
PS:
nasm -f elf64 -F stabs -g sandbox.asm -o sandbox.o
objdump -M intel -d sandbox
我也试过以下汇编器和连接器选项:
nasm -f elf32 -F stabs -g sandbox.asm -o sandbox.o
ld -oformat=elf32-i386 -o sandbox sandbox.o
但它不工作说ld: i386 architecture of input file `sandbox.o' is incompatible with i386:x86-64 output
BITS
指令,除非它是必要的。位指令不会更改-felf64
或-felf32
选择输出文件类型。 (-felf
是-felf32
的代名词,如果你曾经看到,在示例中使用。)
为了让32位的静态可执行文件,我用的就是结束了这样一个asm-link
shell脚本:
nasm -felf32 -g -Fdwarf foo.asm &&
ld -melf_i386 -o foo foo.o
该stabs
调试格式已过时,但只要你的调试器支持它,它可能用于映射ASM源行汇编指令的罚款。无论如何,-Fstabs
是默认的,如果你使用-g
。 (我没有看到这一切,但https://www.ibm.com/developerworks/library/os-debugging/index.html拥有约ブ与矮一些信息。)
大多数的时候,BITS指令是在最好的无用,在最坏的情况积极有害的。相反,像push ebx
不是encodeable如果您尝试建立32位代码为64位的目标文件中的有用错误的,它可以让这样的事情发生。 (虽然它不会在这里救了你,因为所有代码的组装两种方式。)
唯一的一次BITS
是有用的,当你想使用nasm -fbin
,使平坦的二进制你可以喂到ndisasm或使用的shellcode,或定义ELF或任何其他元数据报头自己与db
(A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux)。 nasm
不提供命令行选项来改变默认BITS 16
模式-fbin
。
或者,如果你真的想在一个文件中,在16位靴子,切换到64位模式混合16,32和64位代码:这是主要的用例的BITS
。或者包括一些BITS 32
或BITS 16
机器代码作为您的64位可执行文件的数据。
不要拍你的文件的顶部作为样板的一部分BITS 32
线,这不是有益还是很好的做法。如果你想描述一下在这个源文件,以及如何构建/运行使用像;;; 32-bit x86 Linux code, NASM syntax
评论。
你可以和应该使用虽然DEFAULT REL
,所以如果你正在构建64位代码,你会得到RIP-相对寻址方式为存储器操作数像[somedata]
(符号名没有GP寄存器)。这是一个字节大于32位绝对寻址模式更短,并会在PIE执行工作。
有趣的事实:32位模式具有2点冗余的方式来编码[disp32]
绝对寻址模式。 X86-64改变用途中较小的一个(没有SIB字节)为RIP-相对。这就是为什么在32位计算机代码的64位拆卸具有DWORD PTR [rip+0x6000c0]
其中rel32是符号的绝对地址。
nasm -f elf64 -F stabs -g sandbox.asm -o sandbox.o
这总是会产生一个64位的ELF可执行文件,无论事实,你把32位代码里面。这使得反汇编器来解码的32位机器码就好像它是64位代码,因此奇异结果。该拆卸类似于原始代码的事实仅仅是巧合,从以下事实的在64位模式的指令编码是非常相似的或甚至相同(可能更改默认寄存器大小)添加到32位等效导出。
使用-f elf32
得到一个32位的ELF可执行。