【问题标题】:dollar-terminated strings以美元结尾的字符串
【发布时间】:2010-10-03 15:21:02
【问题描述】:

在我的汇编语言课上,我们的第一个任务是编写一个程序,在 DOS 中打印出一个简单的以美元结尾的字符串。它看起来像这样:

BITS 32
    global _main

section .data
    msg db "Hello, world!", 13, 10, ’$’

section .text
_main:
mov ah, 9
mov edx, msg
int 21h
ret

据我了解,$ 符号用于终止字符串,就像 C 中的 null 一样。但是如果我想在字符串中添加一个美元符号该怎么办(比如我想打印出“it cost $30” )?这似乎是一个简单的问题,但我的教授不知道答案,而且我似乎没有使用谷歌搜索找到它。

【问题讨论】:

  • BITS 32??你如何让你的 DOS 程序在 32 位模式下执行,但仍然能够使用int 21h DOS 调用?如果机器代码实际上以 16 位模式执行,则解码的 16 位 mov r16, imm16 指令的长度与发出的 32 位 mov r32, imm32 NASM 的长度不同,因此 msg 地址的高 2 字节将解码作为指示。 (可能是00 00 add [bx+si], al,正好用完这两个字节,让执行到达int 21h,所以你的代码有可能碰巧在16位模式下工作)

标签: assembly console dos nasm


【解决方案1】:

嗯。您可以编写考虑转义$ 的程序集,例如\$? 但是你的\也变成了一个特殊的符号,你需要使用\\来打印\

【讨论】:

  • int 21h / AH=9 是一个 DOS“系统调用”。你不写它的实现,只是调用它。它相当于 ISO C puts 或 fputs(..., stdout) 的 DOS,除了它令人讨厌地使用 '$' 而不是 0 作为终止符。有关逆向计算,请参阅 Why did DOS use dollar-terminated strings?。如果您的意思是编写自己的字符串输出函数,那么首先不要使用$ 终止符。使其使用$,但以与 DOS 不兼容的方式具有接近于零的值。
【解决方案2】:

你不能使用 DOS 的0x09 服务来显示$ 标志,你需要使用0x02。见here。

【讨论】:

【解决方案3】:

试试 '$$'、'\044'(八进制)或 '\x24'(十六进制)

【讨论】:

  • 问题不在于不能在字符串中指定$:键入db "This costs $100." 效果非常好:它将“创建”一个中间带有$ 的字符串。问题是在汇编语言中绝对不可能找出这只是一个字符串还是两个字符串(例如:"This " 和"costs $100.")。 OP 使用的函数使用 $ 来查找字符串的结尾。 "$$" 不起作用,因为“下一个字符串”可能以 $ 开头:"Hello world." 和 "$100" 两个字符串将等于:"Hello world.$$100."
【解决方案4】:

或者使用未记录的 INT 29h(在 AL 中打印字符)创建自己的 print_string 以打印以 NULL 结尾的字符串。

; ds:si = address of string to print
print_string:
    lodsb                   ; load next character from ds:si
    or al, al               ; test for NULL-character
    jz .end_of_string       ; end of string encountered, return.
    int 29h                 ; print character in AL on screen
    jmp print_string        ; print next character
.end_of_string:
    ret                     ; return to callers cs:ip

(假设您使用的是 NASM)

【讨论】:

【解决方案5】:

一种方法是找到打印单个字符的调用。你可以用它打印任何字符。分解字符串并打印“it cost”,然后是“$”,最后是“30”。更多的工作,但它完成了工作。

【讨论】:

    【解决方案6】:

    您可以使用 INT 21H 的 02 服务 代替 09 服务。

    这是示例。

    mov dl, '$'
    
    mov ah,02
    
    int 21h
    

    【讨论】:

      【解决方案7】:

      我更喜欢使用write 服务(AH=0x40):

      • AH=0x40
      • BX 是文件句柄;使用值 1 写入与服务AH=9 相同的设备(例如屏幕)
      • CX 是要写入的字节数;数据没有“终止”(NUL 和 $ 都没有),因此所有值(从 0 到 255)都可以写入
      • DS:DX 指向要写入的数据(在您的情况下:字符串)
        (就像服务 AH=9;如果你使用 32 位 DOS 扩展:EDX,当然)

      该服务实际上是用于将数据写入文件;但是,它也可以通过将BX 设置为 1 来将“字符串”写入“输出”。

      【讨论】:

        猜你喜欢
        • 2012-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-06
        • 1970-01-01
        • 1970-01-01
        • 2023-01-19
        相关资源
        最近更新 更多