【问题标题】:Storing and incrementing integer variables in MASM x86 assembly在 MASM x86 程序集中存储和递增整数变量
【发布时间】:2013-03-23 09:50:21
【问题描述】:

我正在尝试理解汇编。今天的主题是:“存储和递增 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


【解决方案1】:

编辑:重写并添加文本,添加代码(适用于 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:[计数] 添加 dl,'0' ;添加 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) 链接会发出以下警告:

链接:警告 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 小时 结束开始

【讨论】:

  • 当我写“dl,ds:[count]”时,总是打印相同的东西——不管我在 count 中输入了什么:/ 不应该只是“mov dl,count “?我在教程中看到了这一点,但是当我这样做时出现 A02074 错误
  • @Moriquendi 你用的是什么汇编程序?您需要定义数据段,但我认为其语法取决于您使用的汇编程序。
  • 我希望我知道 :P 我已经从教授的网站下载了 MASM 编译器,安装了 32 位 Windows XP 并开始使用示例代码。我怎样才能检查它?其他语法可能是什么样子?
  • @Moriquendi 你的意思是其他汇编程序的语法?好吧,为此检查一些 SO 答案,例如。带有nasm 标签。但是对于 MASM,无论如何您都需要使用 MASM 语法。我以前没有使用过 MASM,但无论如何我现在修复了错误,它在 MASM 6.11 中组装和链接没有问题,并打印所需的输出(对于 0...255 范围内的任何无符号 count 值)。
【解决方案2】:

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

另外这个操作不需要段覆盖前缀,因为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

德克

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    相关资源
    最近更新 更多