Assembly 以美元结尾的字符串

Assembly 以美元结尾的字符串,assembly,console,dos,nasm,Assembly,Console,Dos,Nasm,在我的汇编语言课上,我们的第一个任务是编写一个程序,在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 据我所知,$符号用于终止sting,就像C中的null一样。但是如果我想在字符串中放入一个美元符号(比如我想打

在我的汇编语言课上,我们的第一个任务是编写一个程序,在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

据我所知,$符号用于终止sting,就像C中的null一样。但是如果我想在字符串中放入一个美元符号(比如我想打印“it costs$30”),我该怎么办?这似乎是一个简单的问题,但我的教授不知道答案,而且我似乎无法通过谷歌搜索找到答案。

嗯。您可以编写将转义的
$
考虑在内的程序集,例如
\$

但是你的
\
也变成了一个特殊的符号,你需要使用
\
来打印
\

你不能使用DOS的
0x09
服务来显示
$
符号,你需要使用
0x02
。请参阅。

尝试使用“$$”、“\044”(八进制)或“\x24”(十六进制)

或制作您自己的打印字符串,以使用未记录的INT 29h打印以空结尾的字符串(打印字符为AL)


(假设您使用的是NASM)

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

您可以使用INT 21H的02服务,而不是09服务

这是样品

mov dl, '$'

mov ah,02

int 21h

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

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

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

看起来0x40也可以工作:或者,您可以使用0x40,但这需要您指定要写入的字节数(即,它不使用分隔字符串)。@Jason-Heh,比我快一秒钟。:-)请注意,如果使用INT 29h重定向stdout不起作用(例如test.com>output.txt),首选习惯用法是
test al,al
,用于根据寄存器设置标志<代码>或al,al速度较慢(在现代x86上),而且从来没有比历史x86上的
test
更好。当然,您也可以通过将load和conditional分支放在底部,并使用
jmp
进入
lodsb
来收紧循环。问题不是在字符串中指定< <代码> $>代码>:键入<代码> dB“这要花费100美元。”完全有效:它将在中间创建一个带有<代码> $< /代码>的字符串。问题是,在汇编语言中,绝对不可能确定这是一个字符串还是两个字符串(例如:
“this”
“成本为100美元。”
)。OP使用的函数使用
$
查找字符串的结尾<代码>“$$”不起作用,因为“下一个字符串”可能以
$
开头:两个字符串
“Hello world.”
“$100”
将等于:
“Hello world.$$100”。
int 21h
/AH=9是DOS“系统调用”。您不需要编写它的实现,只需要调用它。它是ISO C
puts
FPUT(…,stdout)
的DOS等价物,只是它恼人地使用
“$”
而不是
0
作为终止符。请参见“反向计算”。如果您的意思是编写自己的字符串输出函数,那么首先就不要使用
$
终止符。使其使用
$
但以与DOS不兼容的方式使用,其值接近于零。
位32
??如何让DOS程序在32位模式下执行,但仍然能够使用
int21h
DOS调用?如果机器代码实际以16位模式执行,则解码的16位
mov r16,imm16
指令的长度与发出的32位
mov r32,imm32
NASM的长度不同,因此
msg
地址的高2字节将作为指令进行解码。(可能是
0000添加[bx+si],al
,精确地使用这两个字节,让执行达到
int 21h
,因此您的代码可能碰巧在16位模式下工作)
mov dl, '$'

mov ah,02

int 21h