Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 无限循环_File_Assembly_X86_Dos_Tasm - Fatal编程技术网

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
clobbers
bx
,在使用
bh
作为循环计数器的循环中调用它


如果您在调试器中运行代码,以便在运行时查看寄存器值,您自己可能会发现这一点。

无限循环的确切位置是哪里?人们还在编写16位代码做什么,特别是使用TASM?:P它已经十年或更长的时间不相关了。@cHao:它似乎在一些学校被用于教育目的(别问我为什么)。见鬼,我曾经参加过一门课程,我们有一些M68000组装实验室作业,而这不是很多年前的事了。@Michael,M68K至少很酷。:)在看过代码之后,我建议重写将AL中的值转换为十六进制字符串的方式。创建十六进制输出不需要使用
div
,这会使IMO变得更加复杂。在这种情况下,使用shift运算符会更合适,并使代码更具可读性。假设这个问题的OP早已消失,这是非常安全的。他们说“最后一次见面是2月4日14日20:11”。也许最好不要问像这样的老问题,除非有什么东西可以补充,对未来的读者可能真的有帮助。如果你想找一个你喜欢的标签,就要翻阅未回答问题的后台档案,很容易回答所有问题,但当OP消失后,将问题从未回答列表中删除将永远不会被“接受”。这当然是我这么做的部分原因(将其从未回答列表中删除),但它也至少有一个未来读者的答案。。。但我真正不明白的是评论中答案的数量。它们(当然)显示为“0个答案”-我讨厌这样。是的,未回答的问题也困扰着我。有些人有一个坏习惯,就是发表评论,而不是给出最少但足够的答案。我经常开始写评论,然后意识到我可以把它作为一个答案发布。然后我通常会花两倍的时间来扩展我要说的内容……并获得更好的最终结果。是的!是的,但我理解为什么回答问题的时间有限的人可能只会发表评论。不管怎么说,大约一年前,当我第一次开始回答很多关于asm的问题时,我查阅了一些未回答的问题的档案,并回答了其中的一些问题,但我很快意识到,在这堆问题上根本没有办法做出多大的改变。不过,我确实发现了一个值得回答的老问题,比如,在哪里有一种通过实验来测试它的方法。