0

我试图理解装配。今天的主题是:“存储和递增 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寄存器则不需要?

4

2 回答 2

3

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

在 x86 汇编中,您需要为指令指定内存操作数的大小,否则会出现歧义。你必须告诉汇编器操作数的大小byte ptr等等word 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 表)。对于小于 10 的数字,以十进制打印很简单,只需添加 '0' ( 30h),如下所示:

mov dl,ds:[计数]
添加 dl,'0' ; 添加 dl,30h

在 x86 汇编中以十进制打印是一个经常被问到的问题,例如看看这个代码是否正确(数字加数字,然后打印结果)来了解这个想法。

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

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

但是与 ML ( ml dosexe.obj) 链接会给出以下警告:

链接:警告 L4021:没有堆栈段

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

.model 小
.stack 4096

数据段定义也有一些问题,我也修复了。

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

.model 小
.stack 4096

。数据
        计数分贝 0

。代码
开始:
        mov ax,seg 计数
        mov ds,ax

        inc 字节 ptr ds:[count]
        inc 字节 ptr ds:[count]
        inc 字节 ptr ds:[count]

; 此代码以十进制打印,无需反转
; 字符串,通过除数。100/10 = 10

        移动 bl,100 ; 原始除数。

        mov al,ds:[计数]

打印循环:
        异或啊,啊;清除被除数的前 8 位(在 ax 中)。
        div bl ; 将 ax 除以 bl。al 中的商,ah 中的余数。

        移动dl,al;要打印的值 ah = 2, int 21h

        移动,啊;余数在下一个循环中被除。
        测试 dl,dl ; 检查数字是否为零
        jz not_print ; 不要打印前导零。

        添加 dl,'0' ; 转换为 ASCII 数字字符范围。
                          ; '0' = 0x30 = 48
        推斧
        mov 啊,2
        诠释 21 小时;根据 Ralf Brown's 打印值
        流行斧; 中断列表返回 al。

not_print:
        推斧
        mov al,bl
        异或啊,啊
        移动 bl,10 ; 将除数除以 10。
        div bl
        mov bl,al ; 新的除数。
        流行斧
        测试 bl,bl
        jnz 打印循环

        mov ah,4ch
        整数 21 小时
结束开始
于 2013-03-23T09:58:35.250 回答
0

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

另外这个操作不需要段覆盖前缀,因为DS是这个操作的默认段。=> mov dl,[计数]

编辑:

定义一个名为 name 的程序段,具有段属性

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

短剑

于 2013-03-28T06:34:35.900 回答