组装,印刷ASCII数字(Assembly, printing ascii number)

2019-07-23 07:08发布

我有我的汇编代码的问题。 我想打印存储在寄存器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

Answer 1:

像这样将工作打印十进制值(新代码为小写)更好:

        mov byte [buffer+9],'$'
        lea si,[buffer+9]

        MOV AX,CX           ;CX = VALUE THAT I WANT TO CONVERT
        MOV BX,10         
ASC2:
        mov dx,0            ; clear dx prior to dividing dx:ax by bx
        DIV BX              ;DIV AX/10
        ADD DX,48           ;ADD 48 TO REMAINDER TO GET ASCII CHARACTER OF NUMBER 
        dec si              ; store characters in reverse order
        mov [si],dl
        CMP AX,0            
        JZ EXTT             ;IF AX=0, END OF THE PROCEDURE
        JMP ASC2            ;ELSE REPEAT
EXTT:
        mov ah,9            ; print string
        mov dx,si
        int 21h
        RET

buffer: resb 10

代替印刷的每个字符的直接将其添加的字符以相反的顺序的缓冲器。 对于值123,将在缓冲液中添加“3”,在缓冲液[8],“2” [7]和“1”,在缓冲器[6] - 因此如果然后打印字符串起始缓冲液+ 6你“123 ”。
我使用NASM语法,但希望它应该足够明确。



Answer 2:

正如迈克尔已经写在他的代码,你需要清除DX,即让它0你把之前。

但如果你问我,如果你只需要显示ASCII格式的数字(如果你想显示的号码没有得到一个笑脸)。 该值在内部转换为ASCII可以说是相当不方便。

你为什么不只是使用在具有数字的所有ASCII值,程序开始定义了一个数组,并挑选一个是对应的。

对于如。 DB arr '0123456789' ,并比较与特定位置的每个编号并打印一个。 这是一个很长的时间,因为我在8086已经编码,但我记得使用这个逻辑,这需要我去打印十六进制数的ASCII值的节目。 所以我用一个数组,有0123456789ABCDEF它完美地工作。

只是我的两分钱。 既然你只想要的结果。 其实并不重要,你如何计算它。



Answer 3:

认为我应该发布一个更新到这一点。 这篇文章真的帮了我寻找一种方式来获得键输入PHP CLI脚本。 我找不到任何地方在Windows / DOS的解决方案,所以我选择了一个外部程序。

我使用的是真正的老版本A86汇编这样的代码是非常基本的。

(和我怎么关闭“运行代码片段”?)

 ;Key input for scripts that can use some "shell" function. ;Waits for a keypress then returns a string "key:scan" ;if "key" is 0 then you can check "scan" for arrow keys ;or other non-ASCII keys this way. mov ah,0 int 16h push ax mov ah,0 mov cx,ax call ASC mov dx,':' call COUT pop ax shr ax,8 mov ah,0 mov cx,ax call ASC jp EXIT COUT: mov ah,2 int 21h ret STROUT: mov ah,9 mov dx,si int 21h ret ASC: mov byte [buffer+9],'$' lea si,[buffer+9] mov ax,cx mov bx,10 ASC_LOOP: mov dx,0 div bx add dx,48 dec si mov [si],dl cmp ax,0 jz STROUT jmp ASC_LOOP EXIT: mov ah,4ch int 21h ret buffer: db " " ; 10 spaces. no "resb" in my assembler. 

样本PHP脚本来测试它:

 <?php function getKey() { return shell_exec("getkey.com"); } print "Press [ESC] to exit.\n\n"; $key = ""; while (ord($key) != 27) { $getch = explode(":",getKey()); $key = chr($getch[0]); $scan = $getch[1]; if (ord($key) != 0) { print $key; } else { print "SCAN:$scan\n"; } } ?> 

诚然毕竟是说,做我意识到我可以在C ++中也做了同样的事情。 但是我学到了很多关于ASM这一次。

所以,再次感谢乡亲!



Answer 4:

这里的打印数量以及测试代码

.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


文章来源: Assembly, printing ascii number