Assembly 检查高达120的数字是否为素数
最新问题:(尝试检查它是否可被2整除) 我正在努力做到这一点:Assembly 检查高达120的数字是否为素数,assembly,x86,dos,Assembly,X86,Dos,最新问题:(尝试检查它是否可被2整除) 我正在努力做到这一点: 输入数字高达120。让我们称之为“num” 如果数字与2,3,5,7,11的余数为零,我需要用余数为零的每个数字打印除法。否则,如果打印该num是质数 e、 g 输入:120。输出:120/2=60,120/3=40 输入:118,输出:118是素数 我所做的: 我扫描前3个数字(我不在乎前3个数字是否为零),然后使用一个简单的算法来构建“num”。我还假设这个数字小于121 如果数字可以被(2,3,5,7,11)中的任何一个
.MODEL SMALL
.STACK 100h
.DATA
DisplayString DB 'Enter number up to 120:', 13,10,'$'
isPrimeNum DB 'is prime', 13,10,'$'
ResultStr DB 13,10, ' / = ' , 13,10,'$'
divisionCalc DB ?
myNum DB ?
two DB 2
three DB 3
five DB 5
seven DB 7
ten DB 10
eleven DB 11
.CODE
Begin:
MOV AX,@DATA
MOV DS,AX
MOV AH,9
MOV DX,OFFSET DisplayString
INT 21h
MOV BL,0 ; Initialize BL to zero!
; //READ 3 DIGITS // ;
;read first digit for e.g. '1'
MOV ah,1h
INT 21h ;read into AL
MOV CL,AL
MOV ResultStr[2], AL
SUB AL,'0' ; Convert the digit from ASCII to DECIMAL
MOV myNum,AL
MOV AH,1
INT 21h
CMP AL,13 ;is it Enter?
JE endInput
MOV ResultStr[3], AL
SUB AL,'0' ;Not enter, let's save this new char
MOV CL, AL ; we save the 2nd char to CL
MOV AL, myNum ; lets move our first char to AL
MUL Ten ; multiply by 10 the first char
MOV myNum,AL ;move that to myNum
ADD myNum,CL ; add to AL the 2nd char.
MOV AH,1
INT 21h
CMP AL,13 ; is it enter?
JE endInput
MOV ResultStr[4], AL
SUB AL,'0' ;Not enter, let's save this new char
MOV CL, AL ; we save the 2nd char to CL
MOV AL, myNum ; lets move our first char to AL
MUL Ten ; multiply by 10 the first char
MOV myNum,AL ;move that to myNum
ADD myNum,CL ; add to AL the 2nd char.
mov AH,1 ; if the number is 3 chars then this will be the enter now.
int 21h
; // FINISH READING 3 DIGITS // ;
endInput:
; AL = AX / two
; AH = AX % two
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
mov CL,[myNum]
DIV two ;div 123 / 2;
CMP AH,0
JNE divThree
;If 123 % 2 = 0, output 123 / 2.
MOV ResultStr[9], '2'
DIV ten
MOV DH,AH
ADD AL,'0'
MOV ResultStr[13], AL
ADD DH,'0'
MOV ResultStr[14], DH
MOV AH,9
MOV DX,OFFSET ResultStr
INT 21h
divThree:
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
DIV three ;div 123 / 3;
CMP AH,0
JNE divFive
;If 123 % 3 = 0, output 123 / 3.
MOV ResultStr[9], '3'
DIV ten
MOV DH,AH
ADD AL,'0'
MOV ResultStr[13], AL
ADD DH,'0'
MOV ResultStr[14], DH
MOV AH,9
MOV DX,OFFSET ResultStr
INT 21h
divFive:
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
DIV five ;div 123 / 5;
CMP AH,0
JNE divSeven
;If 123 % 5 = 0, output 123 / 5.
MOV ResultStr[9], '5'
DIV ten
MOV DH,AH
ADD AL,'0'
MOV ResultStr[13], AL
ADD DH,'0'
MOV ResultStr[14], DH
MOV AH,9
MOV DX,OFFSET ResultStr
INT 21h
divSeven:
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
DIV seven ;div 123 / 7;
CMP AH,0
JNE divEleven
;If 123 % 7 = 0, output 123 / 7.
MOV ResultStr[9], '7'
DIV ten
MOV DH,AH
ADD AL,'0'
MOV ResultStr[13], AL
ADD DH,'0'
MOV ResultStr[14], DH
MOV AH,9
MOV DX,OFFSET ResultStr
INT 21h
divEleven:
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
DIV eleven ;div 123 / 11;
CMP AH,0
JE Skip1
JMP inputIsPrime
Skip1:
;If 123 % 11 = 0, output 123 / 11.
MOV ResultStr[8], '1'
MOV ResultStr[9], '1'
DIV ten
MOV DH,AH
ADD AL,'0'
MOV ResultStr[13], AL
ADD DH,'0'
MOV ResultStr[14], DH
MOV AH,9
MOV DX,OFFSET ResultStr
INT 21h
JMP endProg
inputIsPrime:
MOV AH,9
MOV DX,OFFSET isPrimeNum
INT 21h
endProg:
MOV AH,4Ch
INT 21h
END Begin
编程中的一条规则是“不要重复你自己”。所以每次你复制代码时,你应该问问自己是否可以避免。您可以使用素数的“数组”,而不是在单独的代码块中检查每个素数
num db 118
prims db 2,3,5,7,11 ; these pimes will be checked
然后在这样的循环中检查它们:
start: mov cx, 5 ; number of prims to check
mov si, offset prims
checkPrime:
xor ah, ah ; this is faster than mov ah,0
mov al, [num]
div byte ptr [si]
cmp ah,0
jne skip
;... ; here you do whatever you want to do with non-primes
; or even jump out of the loop, if all you want is to
; determine if [num] is a prime
skip: inc si
dec cx
jnz checkPrime
ps:另外,如果使用循环进行“3位数扫描”会更好,例如,如果您希望将其扩展为读取5位数,甚至是可变数量,如输入16位整数的1-5位数。此外,我还将“输入数字”部分与“解码ascii并对其进行整型”部分分开(首先将所有字符输入缓冲区,然后解码),您可能希望重用它们
您也可以使用函数int 21/A,作为完整值的缓冲输入。除了:您不需要检查
11
,因为它大于120
@WeatherVane的平方根。好吧,在我输入一个0-120之间的数字后,程序终止。算法是将累加器初始化为0
。然后,对于输入的每个数字,它应该是accum=accum*10+数字
,尽管您正确地进行了ASCII调整。@WeatherVane我使用BL进行调整。您不使用10
初始化BL
。而且MUL
不会乘以BL
。汤米,谢谢你的回复。我在帖子中编辑了我的代码。你能看一下吗?我想打印60/2=30,我想打印30。所以我把它除以10,从AL打印3,从AH打印0。这不管用。它打印一个ascii符号,比如心形,或者其他符号,你知道为什么吗?要打印30,你必须打印ascii“3”和ascii“0”。在打印数字值之前,在数字值中添加一个“0”(输入数字时,每个数字都减去“0”,记得吗?这是一样的)ascii“0”-“9”是值0x30-0x39。因此,如果您输入ascii,您必须从每个数字中减去0x30,并且在显示它们时,您需要添加0x30@IlanAizelmanWS:然后完全展开Tommyley的循环,duh。你应该说你不被允许使用循环,因为这是解决像这样重复性任务的唯一好办法。一个完整的展开将非常臃肿且难以阅读,就像你在问题中的代码一样。@IlanAizelmanWS:IDK,我不想阅读那堵由混乱代码组成的巨大墙。使用调试器单步执行,然后查看120何时采用与其他复合数字(如110)不同的路径。(另外,看看x86标签wiki。这里有一个关于样式/格式的链接,可以使代码更易于阅读)。
start: mov cx, 5 ; number of prims to check
mov si, offset prims
checkPrime:
xor ah, ah ; this is faster than mov ah,0
mov al, [num]
div byte ptr [si]
cmp ah,0
jne skip
;... ; here you do whatever you want to do with non-primes
; or even jump out of the loop, if all you want is to
; determine if [num] is a prime
skip: inc si
dec cx
jnz checkPrime