我想做什么
我正在尝试使用数组打印一系列负数和正数。
有什么问题
我无法打印负数。
输入:
2,-3,-4,5,2,9
输出:
2-,529
我的8086汇编代码:
.model small
.stack 100h
.data
elements db 2,-3,-4,5,2,9,'#'
.code
mov ax, @data
mov ds, ax
mov al, 03h
mov ah, 0
int 10h
mov si, 0
;lea si, elements
dis:
cmp elements[si], '#'
je exit
mov dl, elements[si]
add dl, 48
mov ah, 02h
int 21h
inc si
loop dis
exit:
mov ah, 04ch
int 21h
end
注意:我是一个完整的初学者。
答案 0 :(得分:2)
您的计划有两个主要问题:
您正在使用loop
指令而未事先初始化计数器寄存器CX
!幸运的是,您的代码在CX
寄存器之上有一个额外的终止条件,可能从零开始。然后认为你在这个程序中甚至不需要这个指令。
您永远不会测试您从阵列中读取的数字是正数还是负数。
以下是一个包含其他重要评论的完整解决方案:
xor si, si ;Same as "mov si,0"
dis:
mov bl, elements[si]
cmp bl, '#'
je exit
test bl, bl ;Same as "cmp bl, 0"
jns IsPositive
mov dl, "-" ;First display a minus sign
mov ah, 02h
int 21h
neg bl ;Turn the negative number into a positive number
IsPositive:
mov dl, "0"
add dl, bl ;Change the value [0,9] into character ["0","9"]
mov ah, 02h
int 21h
inc si
jmp dis ;Unconditionally jump back. Don't use "loop"
exit:
mov ax, 4C00h ;Always use the full AX, the API defines it that way!
int 21h
答案 1 :(得分:0)
这条指令
add dl, 48
将dl
(从elements
数组设置)中存储的值加48,以将其映射到相应的ASCII数字(ASCII" 0" == 48)。
当dl
为负数时,结果将少于而不是48,并将映射到数字范围之外的ASCII字符。例如,处理-3时:
mov dl, -3
add dl, 48
将导致dl
包含 45 。这映射到ASCII -
(减号/破折号),这就是应该输出的内容。
假设elements
中的每个值代表一个数字(0-9),您需要测试elements
中的值是否为负值,取其绝对值,然后 add 指向48以获得正确的数字ASCII值。然后,您需要输出一个减号(ASCII 45),然后输出新计算的ASCII数字。
答案 2 :(得分:0)
由于您是初学者,我将“修复”您的代码以正确地执行错误的操作(根本不需要编写新代码来执行正确的操作,因为这会有太多更改)。
.model small
.stack 100h
; array terminator changed to -128, because signed bytes values can be -128 to +127
; so this new terminator allows for array with values -127 to +127
ARRAY_TERMINATOR EQU -128
; the old '#' is value 35, which makes weird possible range: [-128, +34] U [+36, +127]
.data
elements db 2,-3,-4,5,2,9,ARRAY_TERMINATOR
.code
mov ax, @data
mov ds, ax
mov ax, 03h ; ax = 3 <=> ah = 0 (set mode), al = 3 (text mode)
int 10h ; set default 80x25 text mode (clears screen)
xor si,si ; si = 0 (common x86 assembly idiom how to set zero)
; but it also destroy flags, so in certain cases the "mov r?,0" is needed.
display_loop: ; use meaningful label names, when possible
; using short labels saves time while writing, but wastes time
; while reading + debugging, which you will do lot more often!
; load value first, so you can also compare it from register (faster/shorter)
mov dl, [elements+si] ; it doesn't hurt anything, when dl = -128 at end
; also I would rather put address label inside brackets, the "elements[]"
; way evokes false feeling, that it is array access from C. It is NOT.
; works like that for byte arrays, but already for WORD you need si*2!
; now it's possible to compare for terminator against register dl
cmp dl, ARRAY_TERMINATOR
je exit
add dl, '0' ; you can use ASCII '0' formatting of value 48 to better tell
; source reader, what you are trying to do, which is adding ASCII digit '0'
; try to write source to reflect your human intentions, you can write
; value 48 in many ways: 48, 30h, '0', 32+16, 3*16 ...
; All of them will compile into the same 48, but each tells different story
; to the reader of the source. +48 is arithmetic, +'0' is conversion to ASCII
mov ah, 02h
int 21h
; the code above will display correct digit only for values 0-9
; any other value will be mangled into some other ASCII character
; check ASCII table to get idea what happens for other values (10+48 = ':')
inc si
jmp display_loop ; don't use loop without initializing "cx"
; and don't use "loop" either, do rather "dec cx" "jnz loop"
; "loop" instruction is artifically slowed down to support some legacy code
; Any way, in this case you don't want to loop per cx count, but until
; array terminator is hit, so use "jmp" instead to jump every time
; to fix the output the inner part of loop would have to:
; display char '-' when value is negative (for example for value -123).
; convert absolute value into digit characters in base-10 (decimal) formatting
; which involves dividing the value by 10 until zero and remembering remainders
; For example |-123| = +123 => would produce remainders: 3, 2 and 1
; Then you add '0' to each remainder, and display them in reversed order.
; display ', ' characters (for start even after last number, when works, improve)
; (logic to avoid last comma requires often some thought and more code
; one usual way is to display first number without comma, and rest of array
; starts by displaying comma, then number)
exit:
mov ah, 04ch
int 21h
end
(但至少我添加了一些“概述”,需要做些什么才能以预期的方式显示数字......无论如何,首先要注意我在第一个版本中更改的微小细节)