组件 8086 打印有符号个位数整数



我写了一个程序来获取数组中的最小数字, 但我无法在屏幕上打印它:(( 我认为问题是将其转换为 ASCII。

.model small
.stack 100h
.data
x db 0,5,-1,4,2     ;my array
min db 0            ;variable to store the smallest number
msg db "The min number is: $"
.code
main PROC
mov ax,@data
mov ds,ax
xor cx,cx
mov cl,5          ;set count to 5
mov si,0          ;start at index 0
L1:
mov dl,x[si]     ;can't compare memory to memory so I moved x[si] to dl
cmp min,dl       ;checks to see if the value in dl is smaller than 
;value in min
JNB no          
mov min,dl       
no:
inc si
loop L1
mov ah,09
mov dx,offset msg    ;print the message
int 21h
cmp min,0            ;check if number is negative or positive
JB minus
mov ah,02
mov dl,min
int 21h
minus:                 ;if minus print the minus sign
mov ah,02
mov dl,'-'
int 21h
*mov ah,02
mov dl,min
or dl,30h        ;here's my error can't print value of min
int 21h*
mov ah,04ch      ;exit code
int 21h
main ENDP
END main

另外,如果有人有很好的资源或学习80386汇编保护模式的书,请在此处提及:))

你的代码有两个问题(除了显示负数)

1.在 NUM 变量中放置零

如果您的数组包含非零数字怎么办,例如:5, 4, 7, 1它应该打印 1,因为它是最小数字,但您的代码将打印 0,这在数组中甚至不存在。

2.使用JNB和JB指令

这些指令仅用于正整数,这里有一个看看JNB JB。您必须使用 JNG 和 JG,因为您的数组包含负数。

以下是检查数组中最小数的程序(无论它包含负数还是正数,它都可以在两种情况下工作,并且还显示了如何打印负数):

.model small
.stack 100h
.data
num db 7,5,3,4,2      ;my array
msg db "The min number is: $"               
.code
main PROC
mov ax,@data
mov ds,ax
mov ax, 0
mov bl, num [0]  ; store first element of array in bl
mov cx, 4
mov si, 1        ; index of second element
calMin:
mov al, num [si] 
cmp bl, al       
jng continue  ; jng is used for signed numbers
mov bl, al      ; exchange values if smaller
continue:   
inc si       
loop calMin 
mov ah, 09h
mov dx, offset msg
int 21h        
mov cl, bl
neg cl         ; 2's complement the min number ( to check if its negative or positive number )                         
js posNum      ; jmp to posNum if sign flag is set
mov bl, cl
jz posNum                       
negNum:
mov ah, 02h
mov dl, '-'     ; print minus symbol if negative number
int 21h
posNum:
mov ah, 02h     
mov dl, bl
add dl, 48
int 21h  
exit:                                    
mov ah,04ch      
int 21h
main ENDP
END main

相关:在 16 位模式下的现代 x86 CPU 上,您可以使用带有范围偏移的 SSE4.1phminposuw,使其适用于有符号输入。 您可以在一条指令中找到 8 个元素中的最小值:x86 程序集 - 4 个给定数字中的 2 个最大值。 使用pmovsxbw xmm0, [num]加载有符号字节。


实现最小值查找循环的更有效方法是避免缓慢的loop指令,并在没有新的最小值时避免采用分支(循环分支除外)。 我本可以通过使用loop和/或使用正常采用的jge跳过循环中的指令来缩小代码,而不是陷入通常不运行的代码中。

相关:在数组中查找第二大值的汇编程序。 我在那里使用了类似的循环结构。

与端点指针进行比较是有效的,无论是常量还是在寄存器中。 作为即时,它将指令保存在循环之外。 我们也不需要用循环计数器捆绑CX;我们已经在SI中有了指针.

这个答案的要点是用于打印前导-的更紧凑的代码,就像我在@Ahtisham答案的评论中提到的。 请参阅下面main的第二部分。

.model small
.stack 100h
.data
num db 0,5,-1,4,2      ;my array
numEnd:
numSize = numEnd - num
msg db "The min number is: $"               
.code
main PROC
mov   ax, @data
mov   ds, ax
mov   si, OFFSET num
mov   bl, [si]          ; bl = min
calMin:                      ; do {
cmp  si, OFFSET numEnd-1
jae  endloop          ; if (p >= end-1) break;
inc  si               ; p++
cmp  bl, [si]
jle  calMin           ; if (*p <= min) continue;  signed compare
; on new min, fall through and update BL before continuing
mov  bl, [si]         ; min = *p
jmp  calMin         ; } while(1);
endloop:
;;; BL = min.  Do whatever you want with it.

现在我们有数组的最小值bl.

通常,您会加载到寄存器中,而不是使用多个加载,但对于大多数输入,mov al, [si]很少运行。 重新加载相同的值很快(因为缓存),因此在常见情况循环中保存指令是一个胜利,即使这意味着当我们找到新的最小值时需要额外的负载。

给定一个个位数的有符号minbl,我们可以打印它(如果它是负数,则用-):

; we could print the message before the loop
; if we wanted to avoid clobbering registers.
mov  ah, 09h         ; print a message first
mov  dx, offset msg
int  21h         ; al = write string to stdout(ds:dx)
mov  dl, bl    ; in case it's positive
neg  bl        ; bl = 0 - bl   setting flags accordingly
jle  posNum    ; if (0 <= num) skip the leading '-'
mov ah, 02h
mov dl, '-'     ; print minus symbol if negative number
int 21h         ; al = print char to stdout(dl)
mov  dl, bl    ; the negated value is positive, print it
posNum:
; absolute value of single-digit number in DL
mov ah, 02h
add dl, '0'
int 21h       ; al = print char to stdout(dl)
exit:
mov ax, 04c00h      ; AL = 0 (exit status), AH = 4C (Exit function)
int 21h
main ENDP
END main

您无需使用单独的jsjz说明分别测试SFZF。 如果原始数字为负数,我使用neg后的jle,因为它根据0 - num设置标志。 即 如果0 <= num,则取jle,即num是非负数的,我们不应该打印'-'

我本可以做到的

test bl, bl
jge  posNum

因为test same,same设置的标志与cmp bl, 0相同。 当然,对于大于或等于零的数字,jge

。请注意,0 - 128确实会溢出,因此仅在neg后测试SF并不等同于jlejle是正确的,js不是。

但是我们的打印首先只处理个位数的整数。 如果这就是您所拥有的,请在打印可选'-'后,使用众多多位数函数之一将绝对值打印为无符号整数。

最新更新