在MASM x86程序集中存储和递增整数变量

问题描述 投票:0回答:2

我正在努力了解装配。今天的主题是:“存储和增加int变量和打印数字”:)

所以这是我的代码

dane segment
     count     db     0
dane ends

code segment
start:
     inc     byte ptr ds:[count]
     inc     byte ptr ds:[count]
     inc     byte ptr ds:[count]

     mov     dl,ds:[count]
     mov     ah,2
     int     21h

     mov     ah,4ch
     int        21h
code ends
end start

当我编译并运行时,我收到此错误:

只有当count增加一次以上时才会发生这种情况。我做错了什么?

有人可以解释为什么我不能简单地写:

inc     count

另外,为什么我在递增值时必须放byte ptr,但如果我将它复制到dl寄存器则不行?

assembly x86 dos masm x86-16
2个回答
3
投票

编辑:重写并添加文本,添加代码(在MASM 6.11中工作):

在x86中,你需要指定内存操作数的大小,否则会出现歧义。你必须用byte ptrword ptr等告诉汇编程序操作数的大小。因此inc byte ptr ds:[count]需要byte ptrinc word ptr ds:[count是不同的指令。

mov dl,ds:[count]不需要byte ptr,因为dl是一个8位寄存器,因此内存操作数的大小总是相同的,一个字节(8位)。

要打印字符,您需要先将数字转换为字符串(或者将数字转换为小于10的数字)。否则,您将打印具有ASCII代码3的控制字符ETX(请参阅ASCII table)。对于小于10的数字,以十进制打印是微不足道的,只需添加'0'(30h),如下所示:

mov     dl,ds:[count]
add     dl,'0'        ; add dl,30h

在x86汇编中以十进制打印是经常被问到的,例如参见Is this code correct (Number plus number, then print the result)以获得想法。

编辑:EXE文件也需要一个堆栈段。

DOS EXE文件需要有一个堆栈段。使用MASM 6.11进行组装不会发出任何警告或错误,基本上使用dosexe.asm(将dosexe.asm替换为汇编代码文件名)。

但是与ML(ml dosexe.obj)联系会发出以下警告:

LINK : warning L4021: no stack segment

因此,需要添加堆栈段,将以下行添加到源的顶部。

.model small
.stack 4096

数据段定义也存在一些问题,我也解决了这个问题。

整个固定汇编代码可能是这样的(在MASM 6.11中有效):

.model small
.stack 4096

.data
        count     db 0

.code
start:
        mov     ax,seg count
        mov     ds,ax

        inc     byte ptr ds:[count]
        inc     byte ptr ds:[count]
        inc     byte ptr ds:[count]

; this code does the printing in decimal without needing to reverse
; the string, by dividing the divisor. 100/10 = 10

        mov     bl,100     ; original divisor.

        mov     al,ds:[count]

print_loop:
        xor     ah,ah ; clear top 8 bits of the dividend (in ax).
        div     bl    ; divide ax by bl. quotient in al, remainder in ah.

        mov     dl,al     ; the value to be printed with ah = 2, int 21h

        mov     al,ah     ; remainder gets divided in the next loop.
        test    dl,dl     ; check if number is zero
        jz      not_print ; don't print leading zeros.

        add     dl,'0'    ; convert to ASCII numeric characters range.
                          ; '0' = 0x30 = 48
        push    ax
        mov     ah,2
        int     21h       ; print the value, according to Ralf Brown's
        pop     ax        ; interrupt list returns al.

not_print:
        push    ax
        mov     al,bl
        xor     ah,ah
        mov     bl,10     ; divide the divisor by 10.
        div     bl
        mov     bl,al     ; the new divisor.
        pop     ax
        test    bl,bl
        jnz     print_loop

        mov     ah,4ch
        int     21h
end start

0
投票

[quote] mov dl,ds:[count]不需要字节ptr,因为dl是一个8位寄存器,因此内存操作数的大小总是相同的,一个字节(8位)。[/ quote]

此外,此操作不需要段覆盖前缀,因为DS是此操作的默认段。 => mov dl,[count]

编辑:

定义名为具有段属性的名称的程序段

http://msdn.microsoft.com/de-de/library/d06y3478%28v=vs.80%29.aspx

name SEGMENT [[READONLY]] [[align]] [[combine]] [[use]] [[characteristics]] ALIAS(string) [['class']]
  statements
  name ENDS

使用段名称的示例:

CODE SEGMENT use16 'CODE'
assume cs:CODE,ds:DATEN,ss:STAPEL
org 100h
START:
mov ax, DATEN
mov ds, ax

; your instructions

CODE ends

DATEN SEGMENT use32 'DATA'
org 0
VALUE  DD ?
DATEN ends

STAPEL SEGMENT use16 STACK 'STACK'
   DB 10h dup (0)
STAPEL ends

end

如何使用细分和指令:

http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH08/CH08-3.html

...

要使用MASM 6链接16位应用程序,我们需要一个其他链接器。

ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe

短剑

© www.soinside.com 2019 - 2024. All rights reserved.