问题描述
[bits 32]
global _start
section .data
str_hello db "HelloWorld", 0xa
str_hello_length db $-str_hello
section .text
_start:
mov ebx, 1 ; stdout file descriptor
mov ecx, str_hello ; pointer to string of characters that will be displayed
mov edx, [str_hello_length] ; count outputs Relative addressing
mov eax, 4 ; sys_write
int 0x80 ; linux kernel system call
mov ebx, 0 ; exit status zero
mov eax, 1 ; sys_exit
int 0x80 ; linux kernel system call
这里的基本要点是,我需要具有hello字符串的长度才能传递给linux的sys_write系统调用.现在,我很清楚,我可以使用EQU,它可以很好地工作,但我实际上是在尝试了解此处的情况.
The fundamental thing here is that I need to have the length of the hello string to pass to linux's sys_write system call. Now, I'm well aware that I can just use EQU and it'll work fine, but I'm really trying to understand what's going on here.
因此,基本上,当我使用EQU时,它将加载该值,这很好.
So, basically when I use EQU it loads the value and that's fine.
str_hello_length equ $-str_hello
...
...
mov edx, str_hello_length
但是,如果我将此行与DB一起使用
However, if I use this line with DB
str_hello_length db $-str_hello
...
...
mov edx, [str_hello_length] ; of course, without the brackets it'll load the address, which I don't want. I want the value stored at that address
汇编程序不会像我期望的那样在该地址上加载值,而是输出RIP相对地址,如gdb调试器中所示,我只是想知道为什么.
instead of loading the value at that address like I expect it to, the assembler outputs RIP-Relative Addressing, as shown in the gdb debugger and I'm simply just wondering why.
mov 0x6000e5(%rip),%edx # 0xa001a5
现在,我尝试使用eax寄存器代替(然后将eax移到edx),但是然后遇到了另一个问题.我最终遇到了gdb中指出的分段错误:
Now, I've tried using the eax register instead(and then moving eax to edx), but then I get a different problem. I end up getting a segmentation fault as noted in gdb:
movabs 0x4b8c289006000e5,%eax
因此,显然,不同的寄存器产生不同的代码.我想我需要以某种方式截断高32位,但是我不知道该怎么做.
so apparently, different registers produce different code. I guess I need to truncate the upper 32-bits somehow , but I don't know how to do that.
尽管确实找到了一个解决方案",但它看起来像这样:用str_hello_length的地址加载eax,然后加载eax指向的地址的内容,一切都是笨拙的.
Though did kind of found a 'solution' and it goes like this:load eax with str_hello_length's address and then load the contents of address that eax points to and everything is hunky dory.
mov eax, str_hello_length
mov edx, [eax] ; count
; gdb disassembly
mov $0x6000e5,%eax
mov (%rax),%edx
显然试图从内存地址间接加载值会产生不同的代码吗?我真的不知道.
apparently trying to indirectly load a value from a mem address produces different code? I don't really know.
我仅需要帮助您理解这些指令的语法和操作,因此我可以更好地理解为什么要加载有效地址.是的,我想我可以改用EQU并保持愉快的状态,但是我真的感到无法继续,直到我了解DB声明的内容并从其地址中加载.
I just need help in understanding the syntax and operations of these instructions, so I can better understand why how to load effective addresses. Yeah, I guess I could've just switched to EQU and be on my merry way, but I really feel I can't go on until I understand what's going on with the DB declaration and loading from it's address.
推荐答案
答案是不是. x86-64在32位仿真模式下没有RIP相对寻址(这很明显,因为RIP在32位中不存在).发生的事情是nasm正在为您编译一些您尝试以64位运行的可爱的32位操作码. GDB正在将您的32位操作码分解为64位,并告诉您在64位中,这些字节表示相对于RIP的mov. x86-64上的64位和32位操作码重叠很多,以利用芯片中的通用解码逻辑,您会感到困惑,因为GDB分解的代码看起来与您编写的32位代码相似,但实际上,您只是在处理器上抛出垃圾字节.
The answer is it isn't. x86-64 doesn't have RIP-relative addressing in 32-bit emulation mode (this should be obvious because RIP doesn't exist in 32-bit). What's happening is that nasm is compiling you some lovely 32-bit opcodes that you're trying to run as 64-bit. GDB is disassembling your 32-bit opcodes as 64-bit, and telling you that in 64-bit, those bytes mean a RIP-relative mov. 64-bit and 32-bit opcodes on the x86-64 overlap a lot to make use of common decoding logic in the silicon, and you're getting confused because the code that GDB is disassembling looks similar to the 32-bit code you wrote, but in reality you're just throwing garbage bytes at the processor.
这与nasm无关.您正在使用的进程使用的体系结构错误.要么在32位进程中使用32位nasm,要么为[BITS 64]编译汇编代码.
This isn't anything to do with nasm. You're using the wrong architecture for the process you're in. Either use 32-bit nasm in a 32-bit process or compile your assembly code for [BITS 64].
这篇关于32位模式下的NASM x86_64组件:为什么此指令产生RIP相对寻址代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!