File 无限循环
我的程序中的问题是,当我试图从包含字符串的缓冲区中提取一个字符,将一个字符分配给File 无限循环,file,assembly,x86,dos,tasm,File,Assembly,X86,Dos,Tasm,我的程序中的问题是,当我试图从包含字符串的缓冲区中提取一个字符,将一个字符分配给AL寄存器,并调用一个将AL中的字符转换为十六进制的过程时,我得到一个无限循环。这是我的密码: .model small .stack 100H .data about db 'example.exe [/?] [sourceFile2]]',13,10,13,10,9,'/? - help',13,10,'$' err_s db 'Unable to open sourc
AL
寄存器,并调用一个将AL
中的字符转换为十六进制的过程时,我得到一个无限循环。这是我的密码:
.model small
.stack 100H
.data
about db 'example.exe [/?] [sourceFile2]]',13,10,13,10,9,'/? - help',13,10,'$'
err_s db 'Unable to open source file',13,10,'$'
str_term db '$'
sourceF db 12 dup (0)
sourceFHandle dw ?
buffer db 500 dup (?)
.code
START:
mov ax, @data
mov es, ax ; es so we can use stosb function: Store AL at address ES:(E)DI
mov si, 81h
call skip_spaces
mov al, byte ptr ds:[si] ; read first symbol of program parameter
cmp al, 13 ; if there's no parameters
jne _1
jmp help ; then jump to help
_1:
;; do we need to print out help
mov ax, word ptr ds:[si]
cmp ax, 3F2Fh ; if input is "/?" - 3F = '?'; 2F = '/'
jne _2
jmp help ; if "/?" is found, print out help
_2:
;; source file name
lea di, sourceF
call read_filename ; move from parameter to line
push ds
push si
mov ax, @data
mov ds, ax
jmp startConverting
readSourceFile:
pop si
pop ds
;; source file name
lea di, sourceF
call read_filename ; move from parameter to line
push ds
push si
mov ax, @data
mov ds, ax
cmp byte ptr ds:[sourceF], '$' ; if there was nothing to read
jne startConverting
jmp closeF
startConverting:
;; open
cmp byte ptr ds:[sourceF], '$' ; if there was nothing to read
jne source_from_file
mov sourceFHandle, 0
jmp read
source_from_file:
mov dx, offset sourceF ; file name
mov ah, 3dh ; open file command
mov al, 0 ; 0 - reading, 1-writing
int 21h ; INT 21h / AH= 3Dh - open existing file
jc err_source ; CF set on error AX = error code.
mov sourceFHandle, ax ; save filehandle
read:
mov bx, sourceFHandle
mov dx, offset buffer ; address of buffer in dx
mov cx, 500 ; how many bytes to read
mov ah, 3fh ; function 3Fh - read from file
int 21h
mov cx, ax ; bytes actually read
cmp ax, 0 ; if there was nothing to read
jne _6 ; not the end of file
mov bx, sourceFHandle ; end of the file being read
mov ah, 3eh ; close the file
int 21h
jmp readSourceFile ; open another file to read if it was specified in the parameters
_6:
mov si, offset buffer ; read from buffer
cmp sourceFHandle, 0
jne _7
cmp byte ptr ds:[si], 13
je closeF
_7:
push cx ; save big loop CX
sort_out:
lodsb ; Load byte at address DS:(E)SI into AL
push cx ; place cx
mov ah, 40h ; INT 21h / AH= 40h - write to file
int 21h
pop cx
loop sort_out
pop cx
loop read
help:
mov ax, @data
mov ds, ax
mov dx, offset about
mov ah, 09h
int 21h
jmp _end
closeF:
;; close the destination file
mov ah, 3eh ; close
int 21h
result:
MOV si, offset buffer ; source index = buffer coordinates
INC si ; add 1 to si
MOV bh, [si] ; let bh know how many symbols in total
INC si ; go to the symbol itself
mov bl, 0 ; initialize bl counter to 0
jmp char
; print out the text in buffer
mov dx, offset buffer
mov ah, 09h
int 21h
_end:
; add a string terminator to avoid static output
db '$'
mov ax, @data
mov ax, 4c00h
int 21h
char:
LODSB ; take a character from es:si and add it to al
; increment bl
INC bl
MOV dl, al ; add a symbol from al to dl
mov ah,2
int 21h
; try to convert the current symbol in al to HEX and print it out
; =======INFINITE LOOP PROBLEM HERE========
call char_to_hex
DEC bh ; subtract 1 from total amount of symbols
JZ _end ; if bh = 0, end program
JMP char ; if not, jump to other symbol
err_source:
mov ax, @data
mov ds, ax
mov dx, offset err_s
mov ah, 09h
int 21h
mov dx, offset sourceF
int 21h
mov ax, 4c01h
int 21h
;; procedures
skip_spaces PROC near
skip_spaces_loop:
cmp byte ptr ds:[si], ' '
jne skip_spaces_end
inc si
jmp skip_spaces_loop
skip_spaces_end:
ret
skip_spaces ENDP
read_filename PROC near
push ax
call skip_spaces
read_filename_start:
cmp byte ptr ds:[si], 13 ; if there is no parameters
je read_filename_end ; if yes, its the end of the filename
cmp byte ptr ds:[si], ' ' ; if space
jne read_filename_next ; then skip it and jump to the next parameter
read_filename_end:
mov al, '$' ; add '$' to the end
stosb ; Store AL at address ES:(E)DI, di = di + 1
pop ax
ret
read_filename_next:
lodsb ; loads other symbol
stosb ; Store AL at address ES:(E)DI, di = di + 1
jmp read_filename_start
read_filename ENDP
; Char to Hex converting
char_to_hex PROC ; Accept a character, print it's ascii value in hex.
MOV DX, OFFSET AskChar ; Display prompt
MOV AH, 09H
INT 21H
MOV AH, 07H ; Get keyboard input w/ no echo (AL)
INT 21H
MOV CL, AL ; Copy user input (AL) to CL
MOV AX, 0 ; Clear AX (get rid of HO bits)
MOV AL, CL ; Copy user input back into AL
MOV BX, 16 ; Set up the divisor (base 16)
MOV CX, 0 ; Initialize the counter
MOV DX, 0 ; Clear DX
Div2:
; Dividend (what's being divided) in DX/AX pair, Quotient in AX, Remainder in DX.
DIV BX ; Divide (will be word sized).
PUSH DX ; Save DX (the remainder) to stack.
ADD CX, 1 ; Add one to counter
MOV DX, 0 ; Clear Remainder (DX)
CMP AX, 0 ; Compare Quotient (AX) to zero
JNE Div2 ; If AX not 0, go to "Div2:"
getHex2:
MOV DX, 0 ; Clear DX.
POP DX ; Put top of stack into DX.
ADD DL, 30h ; Conv to character.
CMP DL, 39h
JG MoreHex2
HexRet2:
MOV AH, 02h ; 02h to display AH (DL)
INT 21H ; Send to DOS
LOOP getHex2 ; If more to do, getHex2 again
; LOOP subtracts 1 from CX. If non-zero, loop.
JMP Skip2
MoreHex2:
ADD DL, 7h
JMP HexRet2 ; Return to where it left off before adding 7h.
Skip2:
RET
char_to_hex ENDP
end START
我的任务是获得如下输出:
00000000 4d 61 6e 6f 20 62 61 74 61 69 20 62 75 76 6f 20 ¦Mano batai buvo ¦
00000010 64 75 2c 0a 56 69 65 6e 61 73 20 64 69 6e 67 6f ¦du,.Vienas dingo ¦
00000020 20 2d 20 6e 65 72 61 6e 64 75 2e 0a 41 f0 20 73 ¦ - nerandu..Aš s ¦
00000030 75 20 76 69 65 6e 75 20 62 61 74 75 6b 75 0a 4e ¦u vienu batuku.N¦
00000040 69 65 6b 75 72 20 65 69 74 69 20 6e 65 67 61 6c ¦iekur eiti negal ¦
00000050 69 75 2e 0a ¦iu..¦
00000054
尽管我的程序需要更多的工作才能得到这样的结果,但我至少希望正确地将字符转换为十六进制部分。您是否从另一个练习中选择了
char\u to\u hex
,并将其粘贴到此程序中?这将解释这一部分:
; Char to Hex converting
char_to_hex PROC ; Accept a character, print it's ascii value in hex.
MOV DX, OFFSET AskChar ; Display prompt
MOV AH, 09H
INT 21H
MOV AH, 07H ; Get keyboard input w/ no echo (AL)
INT 21H
我在任何地方都找不到
AskChar
符号,所以谁知道打印的是什么-但最后两行(耐心地)在键盘上等待给它一个字符。这可能是“无限循环”吗?char\u to\u hex
clobbersbx
,在使用bh
作为循环计数器的循环中调用它
如果您在调试器中运行代码,以便在运行时查看寄存器值,您自己可能会发现这一点。无限循环的确切位置是哪里?人们还在编写16位代码做什么,特别是使用TASM?:P它已经十年或更长的时间不相关了。@cHao:它似乎在一些学校被用于教育目的(别问我为什么)。见鬼,我曾经参加过一门课程,我们有一些M68000组装实验室作业,而这不是很多年前的事了。@Michael,M68K至少很酷。:)在看过代码之后,我建议重写将AL中的值转换为十六进制字符串的方式。创建十六进制输出不需要使用
div
,这会使IMO变得更加复杂。在这种情况下,使用shift运算符会更合适,并使代码更具可读性。假设这个问题的OP早已消失,这是非常安全的。他们说“最后一次见面是2月4日14日20:11”。也许最好不要问像这样的老问题,除非有什么东西可以补充,对未来的读者可能真的有帮助。如果你想找一个你喜欢的标签,就要翻阅未回答问题的后台档案,很容易回答所有问题,但当OP消失后,将问题从未回答列表中删除将永远不会被“接受”。这当然是我这么做的部分原因(将其从未回答列表中删除),但它也至少有一个未来读者的答案。。。但我真正不明白的是评论中答案的数量。它们(当然)显示为“0个答案”-我讨厌这样。是的,未回答的问题也困扰着我。有些人有一个坏习惯,就是发表评论,而不是给出最少但足够的答案。我经常开始写评论,然后意识到我可以把它作为一个答案发布。然后我通常会花两倍的时间来扩展我要说的内容……并获得更好的最终结果。是的!是的,但我理解为什么回答问题的时间有限的人可能只会发表评论。不管怎么说,大约一年前,当我第一次开始回答很多关于asm的问题时,我查阅了一些未回答的问题的档案,并回答了其中的一些问题,但我很快意识到,在这堆问题上根本没有办法做出多大的改变。不过,我确实发现了一个值得回答的老问题,比如,在哪里有一种通过实验来测试它的方法。