检查数字是否可以被 2 整除,如果是,打印数字
Check if number is divisible by 2, if yes, print the number
嗯,这是我的一段 ASM 代码:
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
DIV two ;div 123 / 2;
CMP AH,0
JNE inputIsPrime
;If 123 % 2 = 0, output 123 / 2.
DIV ten
MOV DH,AH
SUB AL,'0'
MOV AH,2
MOV DL, AL
INT 21h
MOV divisionCalc,DH
MOV AH,2
MOV DL,DH
INT 21h
JMP endProg
我想在这里实现的是,在我向键盘输入“60”并按回车键后,我得到了错误的输出。我想得到数字“30”,因为 60/2 = 30。
如果我输入 42,我想得到 21 作为输出。
知道我的代码为什么会失败吗?
完整代码如下:
.MODEL SMALL
.STACK 100h
.DATA
DisplayString DB 'Enter number up to 120:', 13,10,'$'
isPrimeNum DB 'is prime', 13,10,'$'
goodMSG DB 'good', 13,10,'$'
badMSG DB 'bad', 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
SUB AL,30h ; Convert the digit from ASCII to DECIMAL
MOV myNum,AL
MOV AH,1
INT 21h
CMP AL,13 ;is it Enter?
JE endInput
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
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
DIV two ;div 123 / 2;
CMP AH,0
JNE inputIsPrime
;If 123 % 2 = 0, output 123 / 2.
DIV ten
MOV DH,AH
SUB AL,'0'
MOV AH,2
MOV DL, AL
INT 21h
MOV divisionCalc,DH
MOV AH,2
MOV DL,DH
INT 21h
JMP endProg
inputIsPrime:
MOV AH,9
MOV DX,OFFSET isPrimeNum
INT 21h
endProg:
MOV AH,4Ch
INT 21h
END Begin
最简单的除以二的方法,就是右移一个位的值
位移位将存储在进位标志中
所以
shr AX,1
jnc isDividable ; no carry set = there was no division "rest"
将检查 AX 是否可以被 2 整除
测试偶数最有效的方法是测试低位:
test AL,1
jz isEven
这是非破坏性的,并且会宏融合到现代 CPU 上的单个测试和分支 uop。
在这种情况下,如果您想要除以 2 的结果以便打印,那么移位是一个好方法。请参阅汤米的回答。
还有其他用例可以将一个位移出到CF
:例如遍历整数中的位。
嗯,这是我的一段 ASM 代码:
MOV AH, 0 ;reset AH before division
MOV AL,[myNum] ;move the inputed number to AL
DIV two ;div 123 / 2;
CMP AH,0
JNE inputIsPrime
;If 123 % 2 = 0, output 123 / 2.
DIV ten
MOV DH,AH
SUB AL,'0'
MOV AH,2
MOV DL, AL
INT 21h
MOV divisionCalc,DH
MOV AH,2
MOV DL,DH
INT 21h
JMP endProg
我想在这里实现的是,在我向键盘输入“60”并按回车键后,我得到了错误的输出。我想得到数字“30”,因为 60/2 = 30。 如果我输入 42,我想得到 21 作为输出。
知道我的代码为什么会失败吗?
完整代码如下:
.MODEL SMALL
.STACK 100h
.DATA
DisplayString DB 'Enter number up to 120:', 13,10,'$'
isPrimeNum DB 'is prime', 13,10,'$'
goodMSG DB 'good', 13,10,'$'
badMSG DB 'bad', 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
SUB AL,30h ; Convert the digit from ASCII to DECIMAL
MOV myNum,AL
MOV AH,1
INT 21h
CMP AL,13 ;is it Enter?
JE endInput
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
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
DIV two ;div 123 / 2;
CMP AH,0
JNE inputIsPrime
;If 123 % 2 = 0, output 123 / 2.
DIV ten
MOV DH,AH
SUB AL,'0'
MOV AH,2
MOV DL, AL
INT 21h
MOV divisionCalc,DH
MOV AH,2
MOV DL,DH
INT 21h
JMP endProg
inputIsPrime:
MOV AH,9
MOV DX,OFFSET isPrimeNum
INT 21h
endProg:
MOV AH,4Ch
INT 21h
END Begin
最简单的除以二的方法,就是右移一个位的值
位移位将存储在进位标志中
所以
shr AX,1
jnc isDividable ; no carry set = there was no division "rest"
将检查 AX 是否可以被 2 整除
测试偶数最有效的方法是测试低位:
test AL,1
jz isEven
这是非破坏性的,并且会宏融合到现代 CPU 上的单个测试和分支 uop。
在这种情况下,如果您想要除以 2 的结果以便打印,那么移位是一个好方法。请参阅汤米的回答。
还有其他用例可以将一个位移出到CF
:例如遍历整数中的位。