在表达式中减去 NASM 宏的意外结果

Unexpected result of subtracting a NASM macro in an expression

我写了下面的代码:

 section .text
    %define len msg-4
    global _start 
    msg: db "Thank you"
    var: dd 0x31323334

_start:
    mov ecx, msg
    debug:
    mov edx, var-len ; **** the problem is here
    mov ebx, 1
    mov eax, 4
    int 80h
    mov eax, 1 
    mov ebx, 1
    int 80h ; exit         

我希望 edx 保持值 13,因为 var-len= var-msg+4= 13(var 地址与 msg 的距离是 9,因为 msg 是 9 个字节)。因此,我认为这段代码会打印 "Thank you"。

但是,edx 得到了 5,并且打印了 "Thank"。

为什么edx得到5而不是13

看看最上面的一行 - 你说

 section .text
    %define len msg-4
    global _start 
    msg: db "Thank you"
    var: dd 0x31323334

msg - 4,而不是 msg + 4。这就解释了您所看到的差异。

%define len msg-4 是文本替换,见下文。


一般的方法是在一个对象后面加上$ - start来计算长度。简单地标记结束也是有效的。

section .rodata           ; groups read-only together inside the .text section
    msg: db "Thank you"
    var: db 0x34, 0x33, 0x32, 0x31   ; dd 0x31323334  ; Since you're passing these bytes to write(2), writing them separately is probably less confusing.  (x86 is little-endian, so they will come out "backwards")

    ;; apparently you want to include var as part of the message, for some reason
    msglen equ $ - msg    ; $ is the current position

    ;; msgend:            ; alternative: label the end.  There doesn't have to be a db or anything; it's fine to have multiple labels for the same address


section .text
    global _start 
_start:
    mov    edx, msglen        ; message length
    ;; mov edx, msgend - msg  ; alternative

为什么你得到了5

%define 是一个文本替换,就像 C 预处理器。如果您使用 (msg-4),它会按您预期的方式工作。在 CPP 宏中虔诚地使用 () 的所有原因也适用于此。

 %define len msg-4        ; first of all, this is a terrible name: it's not the length!
 mov    edx, var - len    ; expands to var-msg-4,  not var - (msg-4)

 %define msg_minus_varlen  (msg-4)
 mov    edx, var - msg_minus_varlen;  expands to var - (msg-4)

这仍然是一种非常令人困惑的方法。您可以通过从实际要打印的缓冲区中减去偏移量相同的两个位置来获得长度。