Assembly 汇编8086 |数组之和,打印多位数
我已经用asm x8086编写了一个非常简单的代码,但我遇到了一个错误。如果有人能帮我做一个简短的解释,我将不胜感激Assembly 汇编8086 |数组之和,打印多位数,assembly,x86-16,Assembly,X86 16,我已经用asm x8086编写了一个非常简单的代码,但我遇到了一个错误。如果有人能帮我做一个简短的解释,我将不胜感激 IDEAL MODEL small STACK 100h DATASEG ; -------------------------- array db 10h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h sum db 0 ; -------------------------- CODESEG start:
IDEAL
MODEL small
STACK 100h
DATASEG
; --------------------------
array db 10h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h
sum db 0
; --------------------------
CODESEG
start:
mov ax, @data
mov ds, ax
; --------------------------
xor cx, cx
mov al, 0
mov bx, offset array
StartLoop:
cmp cx, 10
jge EndLoop
add al, [bx]
add [sum],al
inc cx
inc bx
jmp StartLoop
EndLoop:
mov ah, 09h
int 21h
; --------------------------
exit:
mov ax, 4c00h
int 21h
END start
正如您在评论中所指出的那样,(注意:add al,[bx]这一行实际上是mov al,[bx])将
add
替换为mov
,这样的更正只不过是标签EndLoop处的函数调用出错了
您希望显示总和,并且正在使用DOS打印功能。此函数09h需要DS:DX中的一个指针,而您没有提供该指针即使您这样做了,您仍然必须转换其文本表示形式中的和数 这里的一个快速解决方案是满足您自己,只需以单个ASCII字符的形式显示结果。硬编码和为52,因此它是一个可显示字符:
EndLoop:
mov dl, [sum]
mov ah, 02h ;Single character output
int 21h
; --------------------------
exit:
mov ax, 4c00h
int 21h
再进一步,我们可以显示“52”:
我没有看到任何错误,代码将对数组求和,显示一些随机的sh*t,然后退出 您可能想显示总和的结果
int 21h,ah=9
将显示dx
指向的内存中终止的字符串
因此,您需要两件事,将[sum]
中的数字转换为结尾以'$'
结尾的字符串,然后将dx
设置为该int 21h
前面的转换字符串
您可以尝试从此处提取number2string
过程:
我个人会将其更改为将si
中目标缓冲区的地址作为另一个调用参数(即从过程体中删除mov si,offset str
)。像这样:
PROC number2string
; arguments:
; ax = unsigned number to convert
; si = pointer to string buffer (must have 6+ bytes)
; modifies: ax, bx, cx, dx, si
mov bx, 10 ; radix 10 (decimal number formatting)
xor cx, cx ; counter of extracted digits set to zero
number2string_divide_by_radix:
; calculate single digit
xor dx, dx ; dx = 0 (dx:ax = 32b number to divide)
div bx ; divide dx:ax by radix, remainder will be in dx
; store the remainder in stack
push dx
inc cx
; loop till number is zero
test ax, ax
jnz number2string_divide_by_radix
; now convert stored digits in stack into string
number2string_write_string:
pop dx
add dl, '0' ; convert 0-9 value into '0'-'9' ASCII character encoding
; store character at end of string
mov [si], dl
inc si
; loop till all digits are written
dec cx
jnz number2string_write_string
; store '$' terminator at end
mov BYTE PTR [si],'$'
ret
ENDP
然后,要在EndLoop
调用此函数,您需要将其添加到数据段numberStr DB 8 DUP(0)
中,以便为字符串分配一些内存缓冲区并添加到代码中:
; load sum as 16b unsigned value into ax
xor ax,ax ; ax = 0
mov al,[sum] ; ax = sum (16b zero extended)
; convert it to string
mov si,OFFSET numberStr
call number2string
; display the '$' terminated string
mov dx,OFFSET numberStr
mov ah,9
int 21h
; ... exit ...
注意:add al,[bx]这一行实际上是mov al,[bx]我想这里有一个简单的解释:(目前还不清楚你在问什么)另外,对于汇编,它总是有助于指定运行代码的目标平台/操作系统,以及编译代码时使用的汇编程序(即使复制所使用的命令行也不要犹豫,有时甚至可能有助于解决问题)。我的意思是,很少有人会查看您的源代码,并且拥有相同的环境,因此他们可以复制/粘贴它,编译并实时查看您的问题。这里的大多数人都会利用他们的知识和经验进行“试运行”在他们的头脑中,为了让他们更容易理解,你应该提供每一个相关的细节(想象一下你自己在阅读问题时对你的设置一无所知)。如果它只是直接存储到缓冲区中,并在div循环中执行
dec si
,而不是推到堆栈上并在单独的循环中弹出,则会更简单、更高效。对于使用int 21h
/ah=9
打印,您不必关心字符串在缓冲区中的起始位置,只需要一个指向起始位置的指针.
; load sum as 16b unsigned value into ax
xor ax,ax ; ax = 0
mov al,[sum] ; ax = sum (16b zero extended)
; convert it to string
mov si,OFFSET numberStr
call number2string
; display the '$' terminated string
mov dx,OFFSET numberStr
mov ah,9
int 21h
; ... exit ...