Assembly 程序集向字符串输入最多8个字符,并输出反向字符串
我有一个家庭作业问题要从用户那里得到,在一个新行的字符串中最多有8个字符,并将其反向打印 我编写了一个代码,它应该从字符串中提取每一位,并将其放入堆栈中,然后将其返回到字符串中,这样它将处于反转状态,并在新行中打印它。但当我运行文件时,它只是停留在输入上,没有给我做什么 我是装配新手,我们使用tasm1~1.4 这是我的代码:Assembly 程序集向字符串输入最多8个字符,并输出反向字符串,assembly,tasm,emu8086,Assembly,Tasm,Emu8086,我有一个家庭作业问题要从用户那里得到,在一个新行的字符串中最多有8个字符,并将其反向打印 我编写了一个代码,它应该从字符串中提取每一位,并将其放入堆栈中,然后将其返回到字符串中,这样它将处于反转状态,并在新行中打印它。但当我运行文件时,它只是停留在输入上,没有给我做什么 我是装配新手,我们使用tasm1~1.4 这是我的代码: STA SEGMENT STACK DB 100H DUP (0) STA ENDS DATA SEGMENT
STA SEGMENT STACK
DB 100H DUP (0)
STA ENDS
DATA SEGMENT
MSG1 DB 'ENTER STRING (Maximum is 8) : $'
MSG2 DB 'REVERS IS : $'
ISTR DB 10 DUP(0)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STA
MAIN:
MOV AX, DATA
MOV DS, AX
LEA DX, MSG1
MOV AH, 09H
INT 21H
MOV DX, 0
;INPUT
MOV DX, OFFSET ISTR
MOV AH, 0AH
INT 21H
MOV SI, DX
MOV CL, [SI+1]
ADD SI, 2
MOV DX, 0
MOV BL, CL
TOSTACK:
MOV DX, [SI]
PUSH DX
INC SI
LOOP TOSTACK
MOV DL, 10
MOV AH, 02H
INT 21H
LEA DX, MSG2
MOV AH, 09H
INT 21H
MOV DX, 0
MOV CL, BL
MOV SI, 2
FROMSTACK:
POP DX
MOV AH, 02H
INT 21H
INC SI
LOOP FROMSTACK
MOV AX, 4C00H
INT 21H
CODE ENDS
END MAIN
但当我运行文件时,它只是停留在输入上
这是因为在使用DOS输入功能0Ah时,需要事先告诉DOS输入缓冲区的大小。使用类似ISTR DB 10 DUP(0)
的定义,您实际上根本没有请求缓冲区程序中的正确定义是
ISTR DB 9, 0, 9 DUP(0)
第一个字节指定输入缓冲区的大小。将其设置为所需的NumberOfCharacters+1。第2个字节指定缓冲区已包含的字符数。把它归零 你可以在我的另一篇文章中找到更多关于DOS函数的信息 一旦输入工作正常,您需要修复程序TOSTACK部分的一些问题:
指令依赖于整个循环
寄存器,但您只填充了CX
,这是CL
的低位字节。只需添加CX
mov ch,0
这显然意味着您还需要复制到
而不是BX
,以准备FROMSTACK部分BL
- 因为用户可以选择根本不提供任何字符,所以您的程序需要为这种情况做好准备。只需退出jcxz即可
- 输入缓冲区中的每个字符都保存在一个字节中。因此,您的代码不应读取单词
循环
指令很容易:
mov si, offset ISTR + 1
mov cl, [si] ; Characters read 0, 1, 2, ... 8
mov ch, 0
jcxz EXIT
mov bx, cx ; Save count
TOSTACK:
inc si
mov dl, [si] ; This is a byte
push dx ; Don't care about high byte in DH
dec cx
jnz TOSTACK
...
FROMSTACK:
pop dx ; Still don't care about DH
mov ah, 02h
int 21h
dec bx
jnz FROMSTACK
EXIT:
mov ax, 4C00h
int 21h
注释你的代码,特别是如果你想让别人帮忙的话。学习使用调试器(例如,非常用户友好的turbo调试器)单步执行代码并查看出错的地方。慢速
循环指令使用CX(在16位模式下),而不仅仅是CL。您正在编写CL,但我看不到您零扩展到CX。IDK为什么在按下按钮之前要在[si+1]
处存储到内存中。如果要手动存储,只需在读取输入时创建一个缓冲区和dec
指针,然后在写入时在其上循环转发即可。(或者将整个缓冲区传递给写字符串函数。)如果您摆脱了循环
,您可以使用dec cl
/jnz
。不使用循环
的好处之一是可以选择循环条件。@PeterCordes我保留了单词extension,因为它在dec-cx
和dec-bx
中提供了更短的编码。减少了两个字节…如果您正在优化代码大小和/或一个真正的8086(其中代码获取是主要的性能瓶颈,因此在循环中节省空间是一个胜利),那么您应该使用loop
。我认为486和更高版本的速度比较慢,但在原版8086上效果很好。谢谢,我会测试一下。我刚开始学习组装。
mov si, offset ISTR + 1
mov cl, [si] ; Characters read 0, 1, 2, ... 8
mov ch, 0
jcxz EXIT
mov bx, cx ; Save count
TOSTACK:
inc si
mov dl, [si] ; This is a byte
push dx ; Don't care about high byte in DH
dec cx
jnz TOSTACK
...
FROMSTACK:
pop dx ; Still don't care about DH
mov ah, 02h
int 21h
dec bx
jnz FROMSTACK
EXIT:
mov ax, 4C00h
int 21h