为什么在 asm 中只要求一个时打印所有声明的变量

why do all the declared variable print when only one was asked for in asm

所以在下面的代码中,我试图只打印再见消息,但所有 3 个都被打印出来,如果添加了 4 个变量,它也会被打印出来。 是什么原因造成的,我该如何解决。

我读过一些关于空终止符的帖子,但是使用

goodbyeMsg db " powering off",0

goodbyeMsg db " powering off$",10, 13, 0

goodbyeMsg db " powering off",10, 13, 0
goodbyeMsg db " powering off$"

没用

示例代码:

section .text
    global _start

    _start:
        mov eax,4
        mov ebx,1
        mov ecx,goodbyeMsg
        mov edx,lenGoodbyeMsg
        int 80h

        mov eax, 1
        mov ebx ,0
        int 80h

section .data
    welcomeMsg db "Welcome, to Ugo Air Condition"
    lenWelcomeMsg db $-lenWelcomeMsg
    goodbyeMsg db " powering off"
    lenGoodbyeMsg  db $-lenGoodbyeMsg
    help db "enter q w e r t y u "
    lenHelp   db  $-lenHelp
    quitKey db "q"
    lenQuitKey equ $ - quitKey
    defaultMode db "Stationary"
    lenDefaultMode equ $-defaultMode

    defaultTemp db 18
    defaultFanSpeed db 2


section .bss
    userInput resb 10
    powerState resb 10
    currentTemp resb 10
    currentMode resb 10
    currentFanSpeed resb 10

输出:

给罪犯 q w e r t y u qStationarys 供电

strace 的结果

execve("./air", ["./air"], [/* 58 vars */]) = 0
[ Process PID=5169 runs in 32 bit mode. ]
enter q w e r t y u qStationary) = 2048 "..., 134516943 powering off
_exit(0)                                = ?
+++ exited with 0 +++

lenGoodbyeMsg db $-lenGoodbyeMsg 在数据部分发出 一个 字节,值为 0 (因为你使用 lenGoodbyeMsg 而不是 goodbyeMsg).

在数据部分中,ent 的 ASCII 代码从 help: 标签后面的数据开始。如果你从 lenGoodbyeMsg 加载了一个双字,你会得到一个非常大的数字。


但是 none 的数据甚至很重要,因为 mov edx,lenGoodbyeMsglenGoodbyeMsg 标签的 地址 放入 edx,并且那个大number 变为 sys_write 的长度 arg。如果你 运行 你的程序在 strace 下,你会看到一个非常大的长度被传递给 sys_write。有点令人惊讶的是 sys_write 不仅在 -EFAULT 时失败而且没有打印任何内容;我猜它在检测到错误之前打印了第一页?

(否则您在重写代码后没有更新问题,该代码最初是 In NASM labels next to each other in memory are causing printing issues 的副本。)


mov edx,lenGoodbyeMsg 如果你写
将是正确的指令 lenGoodbyeMsg equ $ - goodbyeMsg 而不是 db,就像让汇编程序为您计算长度的每个工作示例一样。 因为 lenGoodbyeMsg 将是一个汇编程序常量,而不是地址。

有关详细信息,请参阅 How does $ work in NASM, exactly?


当然,空终止符不起作用:您使用的是 sys_write,它采用指针 + 长度并适用于任意二进制数据。

puts / printf / strstr 这样的 C 库函数采用空终止的隐式长度字符串。

问题出在.data段中写入的db。将它们更改为 equ 解决了我的问题。感谢大家的帮助。