使用MS-DOS int 21h系统调用在汇编语言中打印新行

5
我是一名有用的助手,可以为您翻译文本。
我已经尝试了几天,在nasmide中使用汇编语言打印字母表时同时打印一个新行,但一直无法实现。到目前为止,我尝试过的方法要么什么也没打印出来,要么只打印了A,或者打印了大量符号。Google对我没有帮助,所以我决定在这里发布。

我的代码目前是:

CR equ 0DH
LF equ 0AH

main:
mov AH,02H
mov CX,26
mov DL, 'A'

while1:
cmp DL, 'A'
add DL, 01H
int 21H
mov DL, 0DH
mov DL, 0AH
int 21H
cmp DL, 'Z'
je Next
jmp while1

Next:
mov AH,4CH
int 21h

使用注释在您的汇编中编写代码 - Rafael
7个回答

18

打印换行的代码

MOV dl, 10
MOV ah, 02h
INT 21h
MOV dl, 13
MOV ah, 02h
INT 21h

ascii ---> 10 换行

ascii ---> 13 回车

这是汇编语言中用于换行的代码,灵感来自打字机。我们的教授给我们讲了这个故事,但我不太擅长英语。

干杯 :)


9
不是先13后10吗?CR-LF? - xdevs23
是的,CR LF 是标准的 DOS 行尾顺序。但如果 stdout 输出到屏幕而不是重定向到文件,则 LF 将光标下移一行,CR 将其返回到列 0,因此两者都是必要的,它们的效果是正交的且独立于顺序。这就是为什么在屏幕上实际上可以工作,但会生成奇怪的文件 program.exe > foo.txt。(是的,int 21h / ah=02h 是 STDOUT,而不是特定的屏幕) - Peter Cordes
1
第二个“mov ah,02h”是多余的:使用“ah=2”的“int 21h”保留AH(以及除返回写入字符的AL之外的所有其他寄存器)。一些人使用完整的AX作为返回值,但AH=02h不需要。 - Peter Cordes

4

100%有效。

CR equ 0DH
LF equ 0AH

main: 
    mov DL, 'A'

while1:
    mov AH,02H      ;print character
    int 21H 

    mov BL, DL      ;store the value of DL before using DL for print new line

    mov DL, 10      ;printing new line
    mov AH, 02h
    int 21h
    mov DL, 13
    mov AH, 02h
    int 21h

    mov DL, BL      ;return the value to DL

    cmp DL, 'Z'
    je exit 
    add DL, 1       ;store in DL the next character
    jmp while1

exit:
    mov AH,4CH
    int 21h

使用BL作为您的循环计数器会更容易,并在循环中只有一个mov DL,BL来打印它。此外,您非常接近拥有底部带有jcc的清晰循环结构,但是错过了。如果不使用定义CR和LF,那么使用equ是没有意义的。 - Peter Cordes
我认为你从问题中的糟糕代码开始,并没有修复大部分丑陋的地方。 - Peter Cordes
这个程序可以用许多不同的方式实现,我理解了。我尽量不改变代码的原始版本,以便问题的作者能够轻松地理解更改。 - Igor Osipov
如果您查看发布此问题的用户资料,您会发现他们的“最后一次出现是在2013年4月5日11:50”,大约是在5年前发布此问题后不久。他们不会看到您的答案。是的,有多种实现方法,但对于SO答案而言,最好的例子是一个干净高效且尽可能简单的版本,从原始代码中删除过度复杂的部分。 - Peter Cordes
完全同意您的观点。您可以将程序更正到理想状态并发布它。也许将来会有人遇到类似的问题并找到您的答案。提问者可能已经在NASA工作,他不需要我们的建议 :) 最好的祝福。 - Igor Osipov

3

首先:

mov DL, 0DH
mov DL, 0AH
int 21H

这样做没有任何好处。你将0Dh加载到DL中,然后立即使用0Ah覆盖它,而从未使用第一个值... 你需要在两个字符上进行调用(int 21h)...

此外,你正在使用DL作为换行符,覆盖了先前用于该字符的使用... 你需要根据需要保存和恢复该值。


0

你可以直接使用

 mov ah, 02h
 mov dl, 13
 int 21h
 mov dl, 10
 int 21h 
 ret

但是在您的“main endp”底部将其声明为proc,您可以将该函数命名为newline,并在需要换行的任何地方调用它


0
.MODEL SMALL;Code model set to small
.STACK 100H ;Stack memory 100H size
.CODE       ;Code starts from here

START:      ;Mark start of code segment

INPUT:      ;Mark input of code segment
MOV AH, 1   ;AH=1,Single key input
INT 21H     ;Input in AL
MOV BL, AL  ;BL=AL, Input in BL

OUTPUT:     ;Mark output of code segment
MOV AH, 2   ;AH=2,Single key output
 
MOV DL, 0AH ;DL=0AH, ASCII for newline
INT 21H     ;Print DL
MOV DL, 0DH ;DL=0DH, ASCII for carriage return
INT 21H     ;Print DL

MOV DL, BL  ;DL=BL,Display the input 
INT 21H     ;Print DL


Exit:       ;Mark exit of code segment
MOV AH, 4CH ;4CH = DOS exit fuction. Handover the control to OS and exit program
INT 21H     ;Invoke the instruction for interrupt where there function needs to be executed

标准的DOS行尾是CR LF,而不是LF CR。如果打印到屏幕上,它具有相同的效果,但是如果重定向到文件,则不同。此外,这个问题并不是要求输入,而是打印字母表。 - Peter Cordes

0
Mov Ah,02
Mov dl,42
Int 21
Mov dl,0a ---> next line 
Int 21
Mov dl,43
Int 21

Output: 
B
C

3
不鼓励仅有代码的回答。请点击编辑并添加一些总结性的文字,说明您的代码如何解决问题,或者解释您的答案与之前的答案有何不同。谢谢。 - Nick

-5
mov dl, 0a
int 21h
int 0ah

试一下这个


2
您应该解释为什么以及如何修复这个问题。仅靠代码片段并不是非常有帮助的。 - Toby Speight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接