【问题标题】:Printing a String with a Start and Length Assembly Language使用开始和长度汇编语言打印字符串
【发布时间】:2016-08-28 09:03:23
【问题描述】:

我试图构建一个汇编代码,它要求一个字符串,从打印字符串的位置开始,以及要打印的所需长度。 假设开始和长度总是有效的你能帮我确定开始和长度吗?

它应该如何工作:

Enter String: Hello World
Enter Start: 3
Enter Length: 5
Mid-String: llo W

所以我对如何确定字符串的开头和长度有疑问。我尝试了以下代码中显示的几件事:

.model small
.stack
.data
msg1 db "Enter String:$"
msg2 db 13,10,"Enter Start:$"
msg3 db 13,10,"Enter Length:$"
msg4 db 13,10,"Mid-String:$"
nwln db 13,10
mySample label byte
maxlen db 10
actlen db 0
string db 19 dup (?)
.code
mov ax,@data
mov ds,ax
    lea dx, msg1 ;print msg1
    mov ah,9
    int 21h

    lea dx,mySample ;accept string
    mov ah,0Ah
    int 21h

    mov bh,0
    mov bl,maxlen
    mov string[bx],'$'
    mov ah,9
    lea dx,string   ;print string accept
    int 21h

    lea dx, msg2    ;print msg2 and accept start
    mov ah,9
    int 21h
    mov ah,1
    int 21h
    sub al,30h
    mov bh,0
    mov bl,al

    lea dx, msg3    ;print msg3 and accept length
    mov ah,9
    int 21h
    mov ah,1
    int 21h
    sub al,30h
    mov dl,al

    ;mov maxlen,dl
    mov bh,0
    mov bl,maxlen
    mov string[bx],'$'
    lea dx,msg4     ;print msg4
    mov ah,9
    int 21h
    lea dx,string   ;print mid-string
    int 21h
mov ah,4ch
int 21h
END

输出看起来像:

【问题讨论】:

  • 当您在调试器中单步执行此操作时,您读入的数字实际上是否像您期望的那样最终出现在寄存器中?最后一个int 21h 之前的寄存器中的值是您期望的吗?如果没有,请向后工作,找出事情首先停止按预期运行的位置。
  • Chouny,你的问题有新答案了,看看吧!

标签: assembly x86 dos tasm x86-16


【解决方案1】:

基于对最后几条指令的快速浏览,您实际上是在其中执行偏移和打印(假设您的其余代码只是正确打印和读取字符串):

您忘记将 ASCII 转换为整数,因此您将终止 $ 写入字符串末尾之后的多个字节(准确地说是'0'0 的 ASCII 编码)。

您似乎也没有对任何东西使用起始偏移量。在将atoi(start_offset_string) 加入 BX 之后,很容易做类似lea dx, [string + bx] 的事情。

您的长度从原始字符串的开头开始计算,而不是从偏移位置开始计算。您可能想先进行偏移。

【讨论】:

  • 我完全不明白我的意思是你需要接受一个数字来设置我所做的字符串的开头,我输入的是 mov bl,al.
  • @Chouny:在打印字符串之前,在代码部分的调试器中查看 BL。我在您的代码中看到了该指令,但我仍然认为我的回答是正确的。在没有调试器的情况下编写 asm 就像在蒙着眼睛时构建一个机器人,所以学习使用你的调试器,你就会明白这个答案。
  • BX = 000A,这是真的,然后 BX= 0102 然后是 0002 然后又是 000A。我不知道发生了什么,但我知道它没有开始。
【解决方案2】:

我对您的代码进行了一些小改动以使其正常工作,这些小改动已被注释,基本上,这是正确使用指针(指向起始位置和长度的指针)的问题,我将其替换为寄存器 SIDI

.model small
.stack
.data
msg1 db "Enter String:$"
msg2 db 13,10,"Enter Start:$"
msg3 db 13,10,"Enter Length:$"
msg4 db 13,10,"Mid-String:$"
nwln db 13,10
mySample label byte
maxlen db 10
actlen db 0
string db 19 dup (?)
.code
mov ax,@data
mov ds,ax
    lea dx, msg1 ;print msg1
    mov ah,9
    int 21h

    lea dx,mySample ;accept string
    mov ah,0Ah
    int 21h

    mov bh,0
    mov bl,actlen   ;◄■■■ NOT MAXLEN.
    mov string[bx],'$'
    mov ah,9
    lea dx,string   ;print string accept
    int 21h

    lea dx, msg2    ;print msg2 and accept start
    mov ah,9
    int 21h
    mov ah,1
    int 21h
    sub al,30h
    mov bh,0
    mov bl,al
    mov si,bx       ;◄■■■ SAVE BX IN SI, BECAUSE WE WILL NEED
                    ;◄■■■  BX FOR SOMETHING ELSE (SI = "START").

    lea dx, msg3    ;print msg3 and accept length
    mov ah,9
    int 21h
    mov ah,1
    int 21h
    sub al,30h
    mov bl,al       ;◄■■■ REPLACE DL BY BL BECAUSE DX WILL
                    ;◄■■■ BE USED TO DISPLAY WITH INT 21H.
    ;mov maxlen,dl
    mov bh,0        ;◄■■■ NOW BX = "LENGTH". BUT WE WILL NEED
    mov di,bx       ;◄■■■ BX AGAIN, SO LET'S MOVE "LENGTH" TO DI.

    ;mov bl,maxlen
    add di, si         ;◄■■■ CALCULATE END POSITION.
    dec di, 1          ;◄■■■ MINUS 1 BECAUSE IT STARTS IN 0.
    mov string[di],'$'
    lea dx,msg4     ;print msg4
    mov ah,9
    int 21h
    ;lea dx,string   ;print mid-string
    mov dx,offset string
    add dx,si
    int 21h
mov ah,4ch
int 21h
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-12
    相关资源
    最近更新 更多