Assembly 检查高达120的数字是否为素数

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)中的任何一个

最新问题:(尝试检查它是否可被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)中的任何一个整除,我将打印消息,否则我将跳过消息打印

  • 如果该数字的所有余数都是零,则我打印num是素数

  • 我不确定我是否做到了这一点,因为我在运行DOSBox时遇到了一些问题,你能帮我确定我是否做到了这一点吗

    解决方案

    .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