【问题标题】:Displaying the sum of a table using assembler 8086使用汇编程序 8086 显示表格的总和
【发布时间】:2016-11-23 19:47:41
【问题描述】:

我正在编写一些代码,允许我对表格求和,然后使用汇编语言显示其结果。到目前为止,这是我想出的:

data segment 
  tab      db 9 dup(3 5 8 4 7 1 6 7 0)
  resultat db ?
data ends

code segment 
  xor di, di
  mov cx, 9
Prog: 
  mov al, tab[di]
  add ax, al
  inc di
loop prog
  mov resultat ,ax
  mov ah, 09h
  int 21h
end code

【问题讨论】:

  • 你使用什么汇编程序? MASM、TASM、FASM、NASM...?
  • Ela,您的结果是ax 中的二进制文件,您必须将其转换为字符串才能显示。如果你显示ax,你会在屏幕上看到奇怪的字符。
  • 您的代码的一个问题是您使用相同的寄存器(AX=AH:AL)有两个目的:加载当前字节(AL)并将结果累加到AX .
  • add ax, al 已关闭,因为您从未初始化过 ax。这应该加倍al,因为它是 l.s. ax 的一部分?然后,您将 ax(2 个字节)存储在仅分配 1 个字节内存的 resultat 中。
  • 这个db 9 dup(3 5 8 4 7 1 6 7 0)真的可以在emu8086中编译吗?它会产生 9 个 9 字节的数组吗?这是荒谬的。对于 OP:正确的方法是 db 3, 5, 8, 4, 7, 1, 6, 7, 0 定义 9 个字节。你不想重复 9 次 (DUP) 甚至不应该编译为单个值的东西。使用dup 多次重复单个值。

标签: assembly emu8086


【解决方案1】:

我对您的代码进行了一些更改,并从另一个答案中窃取了 proc number2string(充满 cmets 以帮助您理解):

data segment 
tab db 3,5,8,4,7,1,6,7,0 ;ARRAY OF NUMBERS.
resultat db '     $'  ;STRING WITH 5 CHARS.
data ends
code segment 
mov ax,@data    ;INITIALIZE
mov ds,ax       ;DATA SEGMENT.

xor di,di 
mov cx,9
xor ax,ax       ;CLEAR THE SUM ACCUMULATOR.
Prog:
add al,tab[di]
inc di
loop prog     

call number2string ;CONVERT AX TO STRING IN RESULTANT.

lea dx,resultat
mov ah,09h
int 21h

mov ax, 4c00h  
int 21h        ;TERMINATE PROGRAM.

;------------------------------------------
;NUMBER TO CONVERT MUST ENTER IN AX.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING.
;THE STRING IS STORED IN VARIABLE "RESULTAT".

proc number2string
  mov  bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:       
  mov  dx, 0 ;NECESSARY TO DIVIDE BY BX.
  div  bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
  push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
  inc  cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
  cmp  ax, 0  ;IF NUMBER IS
  jne  cycle1 ;NOT ZERO, LOOP. 
;NOW RETRIEVE PUSHED DIGITS.
  lea  si, resultat
cycle2:  
  pop  dx        
  add  dl, 48 ;CONVERT DIGIT TO CHARACTER.
  mov  [si], dl
  inc  si
  loop cycle2  

  ret
endp  
;------------------------------------------

end code

proc number2string 转换为字符串 ax 中的任意数字并将结果存储在变量 resultat 中(因为它在数据段中定义)。

【讨论】:

  • 完成了,但我不明白 'lea si, resultat' 它是做什么的
  • @ElaHidri,它使si 指向resultat,就像你的tab[di]
【解决方案2】:

可以通过这种方式添加一个字节序列:

code segment 
  xor ax, ax       ; clear AX
  xor dx, dx       ; accumulator for result value
  lea si, tab      ; SI = address of TAB
  mov cx, 9        ; LEN of TAB in BYTEs
Prog: 
  lodsb            ; AL = BYTE PTR [SI] and increment SI
  add dx, ax       ; add 0:AL to DX
loop prog          ; decrements CX and jumps if not 0
  mov resultat, dx ; mov DX=accumulator to variable
  ; PROBLEM    !!!
  mov ah, 09h      ; !!! prints string and not a number !!!
  int 21h
  ; PROBLEM END!!!
  mov ah, 4Ch      ; exit program
  int 21h          
end code

此代码在 DX 中添加 CX=9 BYTE 值。问题是您的“打印”函数不起作用,因为函数AH=09h of INT 21h 在 DS:DX 中打印字符串而不是数字:

Int 21/AH=09h - DOS 1+ - WRITE STRING TO STANDARD OUTPUT
---
AH = 09h
DS:DX -> '$'-terminated string
---
Return:
AL = 24h (the '$' terminating the string, despite official docs which states that nothing is returned) (at least DOS 2.1-7.0 and
NWDOS)

所以要打印DX 中的数字,您必须先将其转换为字符串。

【讨论】:

  • 如何将其转换为字符串
  • 已经有几个 SO 答案涵盖了该主题:thisthisthis。我希望这能让你解决这个问题。
【解决方案3】:
[bits 16]
[org 0x100]

jmp _start

_start:
    mov cl, 0
    mov ah, 0x0e

_loop:
    cmp cl, 10
    je _end

    mov al, byte cl
    or al, 30h ;Convert number to char
    int 0x10

    ;Print a space
    mov al, 0x20
    int 0x10

    inc cl
    jmp _loop

_end:
    mov ax, 0x4c
    int 0x21

【讨论】:

  • 欢迎来到 SO!您应该始终解释您发布的代码
  • 这个答案似乎打印了从 0 到 9 的数字,并且根本没有对数组求和。即使它确实有效,也没有 cmets 解释代码如何回答问题的原因。 SO 不是编码服务;答案的重点是解释,而不仅仅是工作代码(这个答案缺少)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多