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

时间:2016-07-01 17:25:01

标签: assembly nasm

我写了以下代码:

 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个字节)。因此,我认为这段代码会打印“谢谢”。

但相反,edx得到了5,并且打印了“谢谢”。

为什么edx得到5而不是13

2 个答案:

答案 0 :(得分:6)

%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)

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

答案 1 :(得分:0)

看看最上面的一行 - 你说

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

msg - 4,而不是msg + 4.那就在那里解释了你所看到的差异。