嗨,我正在用汇编语言8086制作这个程序,它可以检测'E‘,并将'E’替换成'Egg‘示例:英语:英语!用鸡蛋英语:蛋英语!以下是我的尝试:
.MODEL SMALL
.STACK 100H
.DATA
english DB "In English$"
result DB 100 dup(?)
;english DB "In english: English$"
;In english: You like english and espresso, excellent!
newline DB 10,13,'$'
bigegg DB "Egg$"
smallegg DB "egg$"
.CODE
MAIN PROC
MOV AX, @DATA
MOV DS, AX
mov ah, 09h
lea dx, english
int 21h
mov ah, 09h
lea dx, newline
int 21h
lea si, english ;start from first char
lea di, result
mov cx, 19
loop1:
mov al, [si]
cmp al, 45h ;E
je bige
jne checke
bige:
mov bx, si
mov cx, si
loop2:
mov ah, 02h
mov dl, [di]
int 21h
loop loop2
inc si
mov ah, 09h
lea dx, bigegg
int 21h
jmp change
checke:
cmp al, 65h ;e
je smalle
jne again
smalle:
mov bx, si
mov cx, si
loop3:
mov ah, 02h
mov dl, [di]
int 21h
loop loop3
inc si
mov ah, 09h
lea dx, smallegg
int 21h
jmp change
again:
mov al, [si] ;save I
mov [di], al
inc si
inc di
loop loop1
change:
lea si, english + 3
sub cx, si
mov cx, cx
loop4:
mov ah, 02h
mov dl, [di]
int 21h
loop loop4
MOV AX, 4C00H
INT 21H
MAIN ENDP
END MAIN实际上,我想让我的系统如下所示:如果检测到'e‘,系统首先会删除'In’,然后忽略'e‘,然后打印’鸡蛋‘和'nglish’。但是,当我运行我的代码时,它会打印出空白。如果有人能指点我,我很感激,谢谢你的阅读!
发布于 2022-09-06 10:03:17
这是我的解决办法。我故意没有对其进行过多的优化,以便以简单的方式显示循环的工作原理。它使用像nasm test.asm -o test.com这样的命令(它使用默认的-f bin隐式-f bin格式)组装成一个平面的-f bin格式文件。应该主要与另一个汇编程序一起工作。
我为子程序做了一些行注释和两个协议注释。
cpu 8086
org 256
start:
mov dx, message
mov cx, message_length
call display
mov dx, linebreak
mov cx, linebreak_length
call display
mov si, message
chunkloop:
mov dx, si ; initialise offset of most recent chunk start
byteloop:
mov al, byte [si] ; get this byte
cmp al, 'E' ; check for replacement
je big ; replace big letter -->
cmp al, 'e'
je small ; replace small letter -->
cmp al, 0 ; terminator ?
je end ; yes, end -->
inc si ; -> next byte
jmp byteloop ; loop back to scan next byte
big:
call displaychunk ; display chunk up to this
mov dx, replace_big
mov cx, replace_big_length
call display ; display replacement
inc si ; -> next byte after what we replaced
jmp chunkloop ; jump back and re-initialise dx so it will
; get the start offset of the next chunk
small: ; (same code as for big, different replacement)
call displaychunk
mov dx, replace_small
mov cx, replace_small_length
call display
inc si
jmp chunkloop
end:
call displaychunk ; display the last chunk
mov dx, linebreak
mov cx, linebreak_length
call display
mov ax, 4C00h
int 21h
; INP: ds:dx -> most recent chunk
; ds:si -> byte to be replaced (or terminator)
; REM: Here si points to behind the last byte that we
; want to write to display the chunk. Therefore
; si minus dx is the length we want to write.
; The chunk length may be zero (dx equals si).
displaychunk:
mov cx, si ; get offset behind the chunk
sub cx, dx ; calculate length of chunk
jz emptychunk ; if empty -->
; INP: ds:dx -> message data
; cx = length of message to write
display:
mov bx, 1 ; = stdout handle
mov ah, 40h
int 21h ; write to file handle
emptychunk:
retn
message:
db "In english: English"
message_length equ $ - message
db 0 ; terminator for main loop
replace_big:
db "Egg"
replace_big_length equ $ - replace_big
replace_small:
db "egg"
replace_small_length equ $ - replace_small
linebreak:
db 13,10
linebreak_length equ $ - linebreak一些可能的优化:
si lodsb同时从byte [ds:si]加载和增量lodsb获得一个小或大的字母。
_length等价物可以使用NASM的本地标签来减少标签的键入量(为了更好地与其他汇编程序兼容而避免)。
发布于 2022-09-11 13:42:30
您的代码中有很多错误,ecm的第一个注释总结了其中的大多数错误。我将不重复这一点,但提出了一个解决方案,该解决方案显示一个循环,其中主循环条件在循环(最小化分支)的底部进行测试,并且在循环主体中有附加条件伴随着(嵌套的循环)。
与其逐字符输出结果字符,甚至不是逐块输出结果,我一次都显示结果,同时还附带了一个包含的回车/ linefeed对和必要的$-结束符。为此,源字符串被转换为ASCIIZ字符串(以0结尾的字符串),其最后三个字节用于回车,10用于linefeed,36用于美元符号。(*)
该程序是一个.COM可执行文件。我使用FASM,但很少需要更改才能使用NASM。
与ecm的解决方案相比,我更接近OP使用在DOS下非常常见的以$结束的字符串的尝试。
ORG 256
mov dx, english
mov ah, 09h ; DOS.PrintString
int 21h
mov si, english ; Address of a zero-terminated string
mov di, result
jmp BottomOfLoop
TopOfLoop:
mov bx, bigegg
cmp al, "E"
je .b
mov bx, smallegg
cmp al, "e"
je .b
mov bx, empty
.a: stosb
.b: mov al, [bx]
inc bx
cmp al, "$"
jne .a
BottomOfLoop:
lodsb
cmp al, 0 ; Reached end of the ASCIIZ string ?
jne TopOfLoop ; Not yet
mov dx, result ; Address of a $-terminated string
mov ah, 09h ; DOS.PrintString
int 21h
mov ax, 4C00h ; DOS.Terminate
int 21h
english db "In english: English", 13, 10, "$", 0 ; (*)
bigegg db "Egg$"
smallegg db "egg"
empty db "$"
result rb 100使用rb (对NASM使用resb ),可以避免在文件中包含结果缓冲区,从而使最终的可执行文件保持较小。通常,小型文件加载速度要快一些。
https://stackoverflow.com/questions/73618421
复制相似问题