【问题标题】:printing a memory value on the screen in assembly在汇编中在屏幕上打印内存值
【发布时间】:2015-10-11 07:26:31
【问题描述】:

我编写了一个汇编代码来对五个数字求和。然后将最终值存储在内存中。

dtseg    segment
data     dw       27345,28521,29533,30105,32375
sum      dw       ?  
MSG1     DB "The sum is : $"  
dtseg    ends
;---------------------
cdseg    segment
main     proc     far
     assume   cs:cdseg,ds:dtseg,ss:stseg
     mov      ax,dtseg
     mov      ds,ax
     clc                       ; clear the carry
     mov      si,offset data   ; first location of data
     mov      cx,04            ; setting the counter
     mov      ax,0             ; clear ax
     mov      bx,ax            ; clear bx
back:add      ax,[si]          ; the first round: 0+27345
     adc      bx,0             ; if there is a carry, add that to bx
     inc      si               ; two inc because traversing words
     inc      si
     dec      cx               ; count down
     jnz      back             ; do that for other numbers
     mov      sum,ax           ; the final value
     mov      sum+2,bx         ; the carries are stored in bx

     lea      dx,MSG1          ; trying to display the result
     mov      ah,09h
     int      21h  
     mov      ah, 4cH          ; return to DOS
     int      21h
main     endp
cdseg    ends  
         end      main

我按照这个topic的例子,但是它在emu8086中不起作用

【问题讨论】:

  • 您必须首先将sum 转换为ASCII 字符串。看this example
  • 你想输出一个 32 位的值吗?
  • 我更新了帖子。虽然我的问题和示例之间有一些相似之处,但我的只是一个更好地遵循的 sn-p
  • 在我看来你应该使用sum dd ? (双字)

标签: assembly emu8086


【解决方案1】:

This example 向您展示如何将AX 中的 WORD 值转换为字符串并输出。您想将 DWORD 值转换为字符串。在您的情况下,您可以利用DIV 在寄存器 DX:AX 中划分 DWORD 的优势。在示例中DX 设置为0,因此第一个想法是删除xor dx, dx 行。但是你第一次需要DX,然后你必须清除它,因为它包含DIV之后的剩余部分。诀窍是在 div 之前而不是在它之前执行清除。所以它会第一次使用,每次重复都会清除。

dtseg    segment
data     dw 27345,28521,29533,30105,32375   ; Sum: 147879

sum      dw  ?, ?               ; two WORD = one DWORD
MSG1     DB "The sum is : $"
DECIMAL  db "0000000000$"       ; space for the result
dtseg    ends
;---------------------
cdseg    segment
main     proc     far
     assume   cs:cdseg,ds:dtseg,ss:stseg
     mov      ax,dtseg
     mov      ds,ax
     clc                       ; clear the carry

     mov      si,offset data   ; first location of data
     mov      cx,5             ; setting the counter
     mov      ax,0             ; clear ax
     mov      bx,ax            ; clear bx
back:add      ax,[si]          ; the first round: 0+27345
     adc      bx,0             ; if there is a carry, add that to bx
     inc      si               ; two inc because traversing words
     inc      si
     dec      cx               ; count down
     jnz      back             ; do that for other numbers

     mov      sum,ax           ; the final value
     mov      sum+2,bx         ; the carries are stored in bx

     call mem_to_dec

     lea      dx,MSG1          ; trying to display the result
     mov      ah,09h
     int      21h
     lea      dx,DECIMAL          ; trying to display the result
     mov      ah,09h
     int      21h

     mov      ah, 4cH          ; return to DOS
     int      21h
main     endp

mem_to_dec proc
    mov ax, [sum]
    mov dx, [sum+2]

    mov bx, 10                  ; divisor
    xor cx, cx                  ; CX=0 (number of digits)

    @First_Loop:
        div bx                  ; DX:AX / BX = AX remainder: DX
        push dx                 ; LIFO
        inc cx                  ; increment number of digits
        xor dx, dx              ; Clear DX for the next DIV
        test  ax, ax            ; AX = 0?
        jnz @First_Loop         ; no: once more

        mov di, OFFSET DECIMAL  ; target string DECIMAL
    @Second_Loop:
        pop ax                  ; get back pushed digit
        or ax, 00110000b        ; to ASCII
        mov byte ptr [di], al   ; save AL
        inc di                  ; DI points to next character in string DECIMAL
        loop @Second_Loop       ; until there are no digits left

        mov byte ptr [di], '$'  ; End-of-string delimiter for INT 21 / FN 09h
        ret
mem_to_dec endp

cdseg    ends
         end      main

如果结果不适合AX 寄存器,DIV 将会出现问题。然后你得到一个溢出错误。

【讨论】:

  • 有什么理由更喜欢inc cl(2 字节)而不是inc cx(1 字节)?
  • @mahmood 请注意,这个出色的解决方案实际上是一种特殊情况,股息不得大于 655359。用你的 5 个数字(总和 = 147879)没问题,但不要'不要将其用作将 dword 数字转换为文本的通用解决方案。
猜你喜欢
  • 1970-01-01
  • 2019-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多