MOV从存储器寄存器不与NASM BITS 32个工作

问题描述 投票:2回答:2

我刚开始用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]

我似乎为什么NA​​SM用相对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,和64位计算机使用Linux。
  • 组装使用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

assembly x86 nasm
2个回答
4
投票

TL:DR:不要使用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或任何其他元数据报头自己与dbA Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux)。 nasm不提供命令行选项来改变默认BITS 16模式-fbin

或者,如果你真的想在一个文件中,在16位靴子,切换到64位模式混合16,32和64位代码:这是主要的用例的BITS。或者包括一些BITS 32BITS 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是符号的绝对地址。


4
投票
nasm -f elf64 -F stabs -g sandbox.asm -o sandbox.o

这总是会产生一个64位的ELF可执行文件,无论事实,你把32位代码里面。这使得反汇编器来解码的32位机器码就好像它是64位代码,因此奇异结果。该拆卸类似于原始代码的事实仅仅是巧合,从以下事实的在64位模式的指令编码是非常相似的或甚至相同(可能更改默认寄存器大小)添加到32位等效导出。

使用-f elf32得到一个32位的ELF可执行。

© www.soinside.com 2019 - 2024. All rights reserved.