Assembly 汇编,打印ascii码

Assembly 汇编,打印ascii码,assembly,x86,ascii,x86-16,Assembly,X86,Ascii,X86 16,我的汇编代码有问题。我想打印存储在寄存器cx中的数字,但当我试图打印它时,它打印的是ascii字符而不是ascii数字,所以我决定编写一个过程来将ascii字符转换为ascii值。 问题是,当我试图调用该过程时,程序冻结,我必须重新启动dosbox。有人知道这个代码有什么问题吗?谢谢 P4 PROC MOV AX,CX ;CX = VALUE THAT I WANT TO CONVERT

我的汇编代码有问题。我想打印存储在寄存器cx中的数字,但当我试图打印它时,它打印的是ascii字符而不是ascii数字,所以我决定编写一个过程来将ascii字符转换为ascii值。 问题是,当我试图调用该过程时,程序冻结,我必须重新启动dosbox。有人知道这个代码有什么问题吗?谢谢

P4      PROC                
            MOV AX,CX           ;CX = VALUE THAT I WANT TO CONVERT
            MOV BX,10           
    ASC2:
            DIV BX              ;DIV AX/10
            ADD DX,48           ;ADD 48 TO REMAINDER TO GET ASCII CHARACTER OF NUMBER 
            PUSH AX             ;SAVE AX
            MOV AH,2            ;PRINT REMAINDER STORED IN DX
            INT 21H             ;INTERRUP
            POP AX              ;POP AX BACK
            CMP AX,0            
            JZ EXTT             ;IF AX=0, END OF THE PROCEDURE
            JMP ASC2            ;ELSE REPEAT
    EXTT:
            RET
    P4      ENDP

对于打印十进制值(新代码是小写的),这样做会更好:


它不是直接打印每个字符,而是以相反的顺序将字符添加到缓冲区。对于值123,它将在缓冲区[8]处添加'3',在缓冲区[7]处添加'2',在缓冲区[6]处添加'1',因此,如果您然后打印从缓冲区+6开始的字符串,您将得到“123”。
我使用的是NASM语法,但希望它应该足够清晰。

正如Michael在他的代码中所写的,您需要清除DX,即在除法之前将其设为0

但是如果你问我,如果你只需要以ASCII格式显示一个数字(当你想要显示一个数字时,不要得到一个笑脸)。在内部将值转换为ASCII可能非常不方便

为什么不使用程序开头定义的数组,该数组包含所有ASCII值,然后选择对应的数组

例如,DB arr'0123456789' 并将每个数字与特定位置进行比较,然后打印该数字。自从我用8086编码以来已经有很长一段时间了,但我记得在一个程序中使用了这个逻辑,这个程序需要我打印一个十六进制数的ASCII值。所以我使用了一个数组,它具有
0123456789ABCDEF
,并且工作得非常好


只要我的两分钱。因为你只想要结果。不管你怎么计算它。

觉得我应该发布一个更新。这篇文章确实帮助我找到了一种获取PHPCLI脚本关键输入的方法。我在任何地方都找不到Windows/DOS解决方案,所以我选择了外部程序

我使用的是一个非常旧版本的a86汇编程序,因此代码非常基本

(如何关闭“运行代码段”?)

;可以使用某些“shell”函数的脚本的键输入。
;等待按键,然后返回字符串“key:scan”
;如果“键”为0,则可以检查箭头键的“扫描”
;或者以这种方式使用其他非ASCII键。
莫夫啊,0
int 16h
推斧
莫夫啊,0
mov-cx,ax
呼叫ASC
mov-dx,':'
呼叫法院
爆斧
shr ax,8
莫夫啊,0
mov-cx,ax
呼叫ASC
太平绅士退出
法院:
mov啊,2
int 21h
ret
斯特劳特:
莫夫啊,9
mov-dx,si
int 21h
ret
ASC:
mov字节[缓冲区+9],“$”
lea si,[缓冲区+9]
移动ax,cx
莫夫bx,10
ASC_环:
mov-dx,0
分区bx
加上dx,48
dec si
mov[si],dl
cmp ax,0
jz STROUT
jmpasc_环
出口:
mov啊,4ch
int 21h
ret

缓冲区:db“”;10个空间。我的汇编程序中没有“resb”。
这是经过良好测试的用于打印数字的代码

.186
.model SMALL
.STACK 100h
.data
    HelloMessage db 'Hello World', 13, 10, '$'
    SuperNumber dw 13565
.code

; Writes word number from AX to output
; Usage
; .186
; ....
; mov ax, 13444
; call PRINT_NUMBER

PRINT_NUMBER PROC NEAR  ; Outputs integer word number stored in AX registry. Requires CPU
    ; Save state of registers.
    PUSHA       ; Save all general purpose registers
    PUSH BP     ; We're going to change that.

    ; we need variables

    ; word number;      2 bytes
    ; byte digitsCount; 1 byte

    ; reserving space for variables on stack (3 bytes)
    mov bp, sp; ; bp := address of the top of a stack
    sub sp, 3*8 ; allocate 3 bytes on stack. Addresses of variables will be
            ; number:   WORD PTR [rbp - 2*8]
            ; digitsCount:  BYTE PTR [rbp - 3*8]

    ; Getting digits
    ; number = ax;
    ; digitsCount = 0;
    ; do
    ; {
    ;   push number%10;
    ;   digitsCount++;
    ;   number = number / 10;
    ; }
    ; while (number > 0)
    mov WORD PTR [bp - 2*8], ax ; number = ax;
    mov BYTE PTR [bp - 3*8], 0  ; digitsCount = 0;

    getDigits:          ; do
        mov ax, WORD PTR [bp - 2*8]; number/10: ax = number / 10, dx: number % 10
        ;cwd
        mov dx, 0
        mov bx, 10
        div bx

        push dx         ; push number%10
        mov WORD PTR[bp - 2*8], ax; number = number/10;
        inc byte PTR[bp - 3*8]  ; digitsCount++;

        cmp WORD PTR[bp - 2*8], 0; compare number and 0
        je getDigitsEnd     ; if number == 0 goto getDigitsEnd
        jmp getDigits       ; goto getDigits;
    getDigitsEnd:

    mov ah, 9
    mov dx, offset HelloMessage
    int 21h


    ;while (digitsCount > 0)
    ;{
    ;   pop digit into ax
    ;   print digit
    ;   digitsCount--;
    ;}
    printDigits:
        cmp BYTE PTR[bp - 3*8], 0; compare digits count and 0
        je printDigitsEnd   ; if digitsCount == 0 goto printDigitsEnd

        pop ax          ; pop digit into al
        add al, 30h     ; get character from digit into al

        mov ah, 0eh     ; wanna print digit!
        int 10h         ; BIOS, do it!

        dec BYTE PTR[bp - 3*8]  ; digitsCount--

        jmp printDigits     ; goto printDigits
    printDigitsEnd:

    ; Deallocate local variables back.
    mov sp, bp

    ; Restore state of registers in reverse order.
    POP BP
    POPA

    ; Exit from procedure.
    RET

PRINT_NUMBER ENDP

start:
    mov ax, @data
    mov ds, ax

    mov ah, 9
    mov dx, offset HelloMessage
    int 21h

    mov ax, 64454   
    call Print_Number

    mov ah, 4ch
    int 21h
end start

您需要在分割之前清除
DX
DIV BX
DX:AX
除以
BX
。除了@user786653所说的以外,还有一个问题,就是最终会以相反的顺序打印数字。例如,123将被打印为321,带有您的代码。嘿!我能在这件事上得到一些帮助吗?我试图将这段代码添加到我的代码中,但它向我抛出了一个错误
undefined var:byte[buffer+9]
,这是我学习汇编的第一天,但我无法理解,我已经陷入了“如何将十进制转换为字符串并在屏幕上打印”的困境
.186
.model SMALL
.STACK 100h
.data
    HelloMessage db 'Hello World', 13, 10, '$'
    SuperNumber dw 13565
.code

; Writes word number from AX to output
; Usage
; .186
; ....
; mov ax, 13444
; call PRINT_NUMBER

PRINT_NUMBER PROC NEAR  ; Outputs integer word number stored in AX registry. Requires CPU
    ; Save state of registers.
    PUSHA       ; Save all general purpose registers
    PUSH BP     ; We're going to change that.

    ; we need variables

    ; word number;      2 bytes
    ; byte digitsCount; 1 byte

    ; reserving space for variables on stack (3 bytes)
    mov bp, sp; ; bp := address of the top of a stack
    sub sp, 3*8 ; allocate 3 bytes on stack. Addresses of variables will be
            ; number:   WORD PTR [rbp - 2*8]
            ; digitsCount:  BYTE PTR [rbp - 3*8]

    ; Getting digits
    ; number = ax;
    ; digitsCount = 0;
    ; do
    ; {
    ;   push number%10;
    ;   digitsCount++;
    ;   number = number / 10;
    ; }
    ; while (number > 0)
    mov WORD PTR [bp - 2*8], ax ; number = ax;
    mov BYTE PTR [bp - 3*8], 0  ; digitsCount = 0;

    getDigits:          ; do
        mov ax, WORD PTR [bp - 2*8]; number/10: ax = number / 10, dx: number % 10
        ;cwd
        mov dx, 0
        mov bx, 10
        div bx

        push dx         ; push number%10
        mov WORD PTR[bp - 2*8], ax; number = number/10;
        inc byte PTR[bp - 3*8]  ; digitsCount++;

        cmp WORD PTR[bp - 2*8], 0; compare number and 0
        je getDigitsEnd     ; if number == 0 goto getDigitsEnd
        jmp getDigits       ; goto getDigits;
    getDigitsEnd:

    mov ah, 9
    mov dx, offset HelloMessage
    int 21h


    ;while (digitsCount > 0)
    ;{
    ;   pop digit into ax
    ;   print digit
    ;   digitsCount--;
    ;}
    printDigits:
        cmp BYTE PTR[bp - 3*8], 0; compare digits count and 0
        je printDigitsEnd   ; if digitsCount == 0 goto printDigitsEnd

        pop ax          ; pop digit into al
        add al, 30h     ; get character from digit into al

        mov ah, 0eh     ; wanna print digit!
        int 10h         ; BIOS, do it!

        dec BYTE PTR[bp - 3*8]  ; digitsCount--

        jmp printDigits     ; goto printDigits
    printDigitsEnd:

    ; Deallocate local variables back.
    mov sp, bp

    ; Restore state of registers in reverse order.
    POP BP
    POPA

    ; Exit from procedure.
    RET

PRINT_NUMBER ENDP

start:
    mov ax, @data
    mov ds, ax

    mov ah, 9
    mov dx, offset HelloMessage
    int 21h

    mov ax, 64454   
    call Print_Number

    mov ah, 4ch
    int 21h
end start