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

问题描述:

我试图理解程序集。今天的话题是:“存储和递增INT变量和印刷数字” :)在MASM x86程序集中存储和递增整数变量

因此,这里是我的代码

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 

当我编译和运行,我得到这个错误:

enter image description here

只有当count增加一次以上时才会发生。 我在做什么错?

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

inc  count 

另外,为什么我必须把byte ptr增加值的时候,但如果我把它复制到dl注册?

+0

我不知道这个集会,但你肯定不会增加一个指针,而不是在寄存器中的值?这个错误信息似乎堆腐败.. – Jack 2013-03-23 17:16:30

编辑:更改信息,并添加文本,添加的代码(工作在MASM 6.11):

在86 assembbly你需要指定内存操作数的大小,在将有歧义,否则说明。您必须告知汇编程序的操作数大小为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的单个字符)。否则,你要打印控制字符ETX(见ASCII table)有ASCII码3.对于小于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

当我写“dl,ds:[计数]”,同样的东西打印所有的时间 - 无论我把什么计数:/不应该只是“mov dl,计数”?我在教程中看到了这个,但是当我这样做时,我得到了A02074错误 – msmialko 2013-03-23 10:23:48

+0

@Moriquendi您正在使用哪种汇编语言?您需要定义数据段,但我认为其语法取决于您正在使用的汇编程序。 – nrz 2013-03-23 10:25:11

+0

我希望我知道:P我从教授的网站上下载了MASM编译器,安装了Windows XP 32位并开始使用示例代码。我如何检查它?其他语法的外观可能如何? – msmialko 2013-03-23 10:33:02

[报价] MOV DL,DS:[计]不需要字节的PTR,因为D1是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

德克