使用x86 DOS ASM中的多个模块打印ASCII字符及其对应的十六进制代码

时间:2014-01-08 14:01:02

标签: assembly x86 masm

明天我有一个任务,我正在失去理智,我不知道该怎么做。基本上我必须从位置32到127打印所有字符,并在它们附近以十六进制格式打印它们各自的代码。像这样:

[space char] 20h
! 21h
" 22h
etc

到目前为止,我只设法做到了这一点:http://i.stack.imgur.com/UneFx.png

事情是我不知道如何从十进制值转换为可打印(所以我必须打印例如,如果我想打印字符'3'我需要打印值33h等)十六进制值。

10l9.asm:

; 10. Print on the screen, for each number between 32 and 126, the value of the number (in base 16) and the character whose ASCII code the number is.

assume cs:code, ds:data

data segment public
nr db 32
hex db 20h
data ends

code segment public
extrn   tipar:proc
start:
mov ax, data
mov ds, ax

lea si, nr
cld
bucla:
    cmp nr, 127
    je final
    mov ah, 0
    mov al, nr
    mov bh, 0
    mov bl, hex
    call tipar
    inc nr
    inc hex
jmp bucla
final:
mov ax, 4C00h
int 21h
code ends
end start

print.asm:

    assume cs:code, ds:data
data segment public
    buffer dw 15 dup (?)
    tmp db 5 dup (?), 13, 10, '$'
data ends

code segment public
public tipar    ; the subprogram 'tipar' is made visible to other modules too
tipar:
; input: ax = the number that has to be printed on the screen
; the subprogram prints the number on the screen
; it does not modify the registers, except for ax

; we save the registers so that we can use them inside the subprogram
    push cx
    push dx
; we compute the representation on the number in base 10
    ;mov bx, offset tmp+5  ; bx=the address of the least written digit
    ;mov cx, 10 ; cx = 10 (constant)
    mov si, 0
    mov buffer[si], ax
    mov cx, 5
    spatiere:
        inc si
        mov buffer[si], 32
        loop spatiere       
    inc si
    mov bh, 0
    mov buffer[si], bx
    inc bx
    inc si
    mov buffer[si], 104
    inc si
    mov buffer[si], 13
    inc si
    mov buffer[si], 10
    inc si
    mov buffer[si], '$'

    mov dx, offset buffer
    mov ah, 09h
    int 21h

    pop dx
    pop cx
    ret

code ends
end

我已经设法做到了(部分原因)..我会在下面发布我是如何做的,万一有人有类似的问题:

mov bx, offset tmp+5
mov cx, 16
bucla:
    mov dx, 0
    div cx
    dec bx
    add dl, '0'
    mov byte ptr [bx], dl
    cmp ax, 0
    jne bucla

1 个答案:

答案 0 :(得分:1)

要将一个字节(AL)转换为对应于相应半字节的ASCII代码的两个字节(AX,小端(AL中的高半字节)),可以使用此代码(GNU as):

        .intel_syntax noprefix
        .code16
c2hex:
        mov     ah,al
        shr     al,4
        and     ah,0x0F
        add     ax,0x3030
        cmp     al,0x39
        jbe     1f
        add     al,7
1:      cmp     ah,0x39
        jbe     2f
        add     ah,7
2:      ret

例如,输出适用于STOSW字符串。

与数字/数字相似,字母是连续的。 0x3A(0x30 + 10)和'A'(0x41)之间的差异恰好是7,这是倒数第二行中的数字来自的地方。 (第{2}行在1:标签上检查一封信。)