本文介绍了32位模式下的NASM x86_64组件:为什么此指令产生RIP相对寻址代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

[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相对寻址代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 03:09