如何在程序集 x86 中使用变量

How to work with variables in assembly x86

所以我必须将 'a' 乘以 'b' 次,我试着这样做。我也从我发现的其他问题中提取了一些程序。

.MODEL SMALL

.DATA
a db 3, 4 dup (0)
b db 3, 4 dup (0) ;With the buffer that this provides, this now will allow you to input from the keyboard two double-digit numbers.

.CODE
  mov  ax, @data ;INITIALIZE DATA SEGMENT.
  mov  ds, ax

START:
;a
mov ah, 0ah
mov dx, offset a 
int 21h         
call string2number1 ;convert a to number (a->bx)
mov dx,bx ;(a->ax)
;b
mov ah, 0ah
mov dx, offset b
int 21h
call string2number2 ;convert b to number (b->bx)

;multiplication
mov cx,bx ;b->cx (multiply by cx(b) times)
mov bx,dx ;a->bx (to do a*a)
power:
    mul bx
    loop power
;dx:ax should now contain m^n (i hope)

;displaying dx:ax
    mov     bx,10          ;CONST
    push    bx             ;Sentinel
.a: mov     cx,ax          ;Temporarily store LowDividend in CX
    mov     ax,dx          ;First divide the HighDividend
    xor     dx,dx          ;Setup for division DX:AX / BX
    div     bx             ; -> AX is HighQuotient, Remainder is re-used
    xchg    ax,cx          ;Temporarily move it to CX restoring LowDividend
    div     bx             ; -> AX is LowQuotient, Remainder DX=[0,9]
    push    dx             ;(1) Save remainder for now
    mov     dx,cx          ;Build true 32-bit quotient in DX:AX
    or      cx,ax          ;Is the true 32-bit quotient zero?
    jnz     .a             ;No, use as next dividend
    pop     dx             ;(1a) First pop (Is digit for sure)
.b: add     dl,"0"         ;Turn into character [0,9] -> ["0","9"]
    mov     ah,02h         ;DOS.DisplayCharacter
    int     21h            ; -> AL
    pop     dx             ;(1b) All remaining pops
    cmp     dx,bx          ;Was it the sentinel?
    jb      .b             ;Not yet

;-----------------------------------------
jmp skipProcedures

;CONVERT a TO NUMBER IN BX.
proc string2number1         
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  mov  si, offset a + 1
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx,ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.

  ret 
endp    

;CONVERT b TO NUMBER IN BX.
proc string2number2         
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  mov  si, offset b + 1
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat2:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx,ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat2 ;COUNTER CX-1, IF NOT ZERO, REPEAT.

  ret 
endp    

skipProcedures:
;---------------------------------------
mov ax,4c00h
int 21h         
end start


程序不让我在输入 'a' 后按回车键。 也许我在做乘法循环或试图显示 dx:ax 时错了,但这与让我为 a 写输入有什么关系? 我试图在评论中尽可能多地解释。 我该怎么办?

I keep getting the same error as 'Operand types do not match on lines 18 and 19

那是因为 TASM 知道 ab 变量是 byte-sized 给定的它们是使用 DB 指令定义的,但是您的指令 mov bx,amov cx,bword-sized 操作。所以,一个不匹配。

这就是代码中发生的事情

您的程序正在使用 ab 'variables' 通过 DOS.BufferedInput 函数 0Ah 进行用户输入.阅读有关此功能的所有信息

您的定义应该是这样的:

.DATA
a db 3, 4 dup (0)
b db 3, 4 dup (0)

有了它提供的缓冲区,现在您可以从键盘输入两个两位数。

要真正开始使用这些数字进行计算,您需要将文本字符(输入它们的字符)转换为 [0,99] 范围内的简单数字。
下一个代码为 两位数 a 输入完成此操作:

mov bx, offset a
mov ah, [bx+2]     ; The tens ["0","9"]
mov al, [bx+3]     ; The ones ["0","9"]
sub ax, "00"       ; Converting to [0,9] on both at the same time
aad                ; Combining both: AX = (AH * 10) + AL

mov ax,0   ; Initial result, i.e. m^0
power:
    jcxz power_done
    mul bx
    loop power
power_done:

无论乘以什么值 (BX),此乘法始终为零。那是因为你初始化了AX=0。这与注释“初始结果,即 m^0”不对应。请记住 m^0 = 1.


您正在尝试使用单字符输出函数显示结果。这永远都不够!请参阅 this Q/A 了解正确的方法。