x64 汇编器使用 4 字节还是 8 字节内存地址?

问题描述 投票:0回答:1

我正在阅读 Jo Van Hoey 所著的 2019 年书籍《开始 x64 汇编编程:从新手到 AVX 专业人士》的章节末尾...

这里是摘录(跳到问题的粗体文本):

     1                                  ; hello.asm
     2                                  section .data                                   
     3 00000000 68656C6C6F2C20776F-         msg db      "hello, world",0                       
     3 00000009 726C6400           
     4                                  section .bss                                                   
     5                                  section .text                                                   
     6                                      global main                                 
     7                                  main:
     8                                                                                   
     9 00000000 B801000000                      mov     rax, 1          ; 1 = write     
    10 00000005 BF01000000                  mov     rdi, 1              ; 1 = to stdout         
    11 0000000A 48BE-                       mov     rsi, msg    ; string to display in rsi
    11 0000000C [0000000000000000]
    12 00000014 BA0C000000                  mov     rdx, 12             ; length of the string, without 0
    13 00000019 0F05                        syscall                             ; display the string
    14 0000001B B83C000000                  mov     rax, 60             ; 60 = exit     
    15 00000020 BF00000000                  mov     rdi, 0              ; 0 = success exit code
    16 00000025 0F05                        syscall                             ; quit

图1-4

图 1-4 显示了我们的

hello.lst
。您有一列包含行号,然后一列包含八位数字。该列代表内存位置。当汇编器构建目标文件时,它还不知道将使用哪些内存位置。因此,它从不同部分的位置 0 开始。 .bss 部分没有内存。

我们在第二列中看到汇编指令转换为十六进制代码的结果。例如,

mov rax
转换为 B8,
mov rdi
转换为 BF。这些是机器指令的十六进制表示。另请注意
msg
字符串到十六进制 ASCII 字符的转换。稍后您将了解有关十六进制表示法的更多信息。要执行的第一条指令从地址 00000000 [八个零]开始,占用五个字节:B8 01 00 00 00。双零用于填充和内存对齐

...

下一条指令从地址 00000005 [七个零]开始,依此类推。 内存地址为八位(即8个字节);每个字节有 8 位。因此,地址有 64 位;事实上,我们使用的是 64 位汇编器。 看看

msg
是如何引用的。由于
msg
的存储位置尚不清楚,因此将其称为[0000000000000000] [16个零]

我是汇编新手,所以我的理解是图1-4中的第二列(例如

00000005
)有八位数字,并且由于每个数字都是十六进制的数字,那么每个数字代表4位,或者最大0xF 的值,即 2^4=16。

这是

hello.asm
:

; hello.asm
section .data                                   
    msg db      "hello, world",0                       
section .bss                                                   
section .text                                                   
    global main                                 
main:

        mov     rax, 1          ; 1 = write     
    mov     rdi, 1              ; 1 = to stdout         
    mov     rsi, msg    ; string to display in rsi
    mov     rdx, 12             ; length of the string, without 0
    syscall                             ; display the string
    mov     rax, 60             ; 60 = exit     
    mov     rdi, 0              ; 0 = success exit code
    syscall                             ; quit

而且,这是

makefile

#makefile for hello.asm
hello: hello.o
        gcc -o hello hello.o -no-pie
hello.o: hello.asm
        nasm -f elf64 -g -F dwarf hello.asm -l hello.lst

有人可以帮我理解图1-4中的第二列,或者汇编器创建的内存地址吗?

assembly hex x86-64 memory-address
1个回答
0
投票

这是 NASM 列表,就像您从

nasm -l /dev/stdout -f elf64 hello.asm
进入终端一样。 第二列(行号之后的第一列)相对于该部分的开头有偏移。 8 个十六进制数字是 32 位偏移量或地址,书上对此是错误的。 每个十六进制数字确实只代表 4 位,而不是书上声称的 8 位。

看看msg是如何引用的。因为 msg 的内存位置尚不清楚,所以称为 [0000000000000000] [16 个零]

这部分是正确的,与前面的句子不同。

mov r64, imm64
是将地址放入寄存器的效率最低的方法,但它是你从asm源中得到的,它按照你在16或16中的方式做事32 位模式。

事实上,链接器将填写该 64 位绝对地址。 使用

objdump -drwC -Mintel
反汇编链接的可执行文件以查看它。 (GAS
.intel_syntax noprefix
与 MASM 类似,但与 NASM 的区别主要仅在于寻址模式。Agner Fog 的
objconv
可以反汇编为 NASM 语法。)


现代 64 位代码通常使用 RIP 相对 LEA,例如

lea rsi, [rel msg]
,它在运行时从包含程序计数器(指令指针)的 32 位相对位移的机器代码生成 64 位绝对地址。 请参阅如何将函数或标签的地址加载到寄存器中了解三个选项,对于
-no-pie
Linux可执行文件还包括
mov esi, msg
。 当您使用
-fno-pie
(代码生成选项)进行编译时,编译器将会执行此操作。

这将汇编为 NASM 用于

mov r32, imm32
的相同 32 位操作数大小
mov rax, 1
(已优化为
mov eax, 1
)请注意,其他指令开头缺少
0x4?
REX 前缀字节。 为什么 Linux 上的 NASM 更改 x86_64 程序集中的寄存器涵盖了
mov
的 3 种编码,可以写入整个 64 位寄存器。

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