MS-DOS TASMMASM 函数读取一个 16 位无符号整数
从输入读取一个 16 位无符号整数
此函数使用中断服务 Int 21 / AH = 0Ah 来读取缓冲的字符串。
使用缓冲字符串可以让用户在将其传递给程序进行处理之前查看他们输入的内容。
最多读取六位数(因为 65535 = 2 16 - 1 有六位数)。
除了执行从数字到数字的标准转换之外,此功能还检测无效输入和溢出(数字太大而不适合 16 位)。
返回值
该函数返回 AX
中读取的数字。标志 ZF
,CF
,OF
判断操作是否成功完成以及原因。
错误 | 斧头 | ZF | CF | |
---|---|---|---|---|
None |
16 位整数 | 组 | 没有设置 | 没有设置 |
Invalid input |
部分转换的数字,直到遇到的最后一个有效数字 | 没有设置 | 组 | 没有设置 |
Overflow |
7FFFH | 没有设置 | 组 | 组 |
ZF
可用于快速分辨有效与无效输入。
用法
call read_uint16
jo _handle_overflow ;Number too big (Optional, the test below will do)
jnz _handle_invalid ;Number format is invalid
;Here AX is the number read
码
;Returns:
;
;If the number is correctly converted:
; ZF = 1, CF = 0, OF = 0
; AX = number
;
;If the user input an invalid digit:
; ZF = 0, CF = 1, OF = 0
; AX = Partially converted number
;
;If the user input a number too big
; ZF = 0, CF = 1, OF = 1
; AX = 07fffh
;
;ZF/CF can be used to discriminate valid vs invalid inputs
;OF can be used to discrimate the invalid inputs (overflow vs invalid digit)
;
read_uint16:
push bp
mov bp, sp
;This code is an example in Stack Overflow Documentation project.
;x86/Converting Decimal strings to integers
;Create the buffer structure on the stack
sub sp, 06h ;Reserve 6 byte on the stack (5 + CR)
push 0006h ;Header
push ds
push bx
push cx
push dx
;Set DS = SS
mov ax, ss
mov ds, ax
;Call Int 21/AH=0A
lea dx, [bp-08h] ;Address of the buffer structure
mov ah, 0ah
int 21h
;Start converting
lea si, [bp-06h]
xor ax, ax
mov bx, 10
xor cx, cx
_r_ui16_convert:
;Get current char
mov cl, BYTE PTR [si]
inc si
;Check if end of string
cmp cl, CR_CHAR
je _r_ui16_end ;ZF = 1, CF = 0, OF = 0
;Convert char into digit and check
sub cl, '0'
jb _r_ui16_carry_end ;ZF = 0, CF = 1, OF = X -> 0
cmp cl, 9
ja _r_ui16_carry_end ;ZF = 0, CF = 0 -> 1, OF = X -> 0
;Update the partial result (taking care of overflow)
;AX = AX * 10
mul bx
;DX:AX = DX:AX + CX
add ax, cx
adc dx, 0
test dx, dx
jz _r_ui16_convert ;No overflow
;set OF and CF
mov ax, 8000h
dec ax
stc
jmp _r_ui16_end ;ZF = 0, CF = 1, OF = 1
_r_ui16_carry_end:
or bl, 1 ;Clear OF and ZF
stc ;Set carry
;ZF = 0, CF = 1, OF = 0
_r_ui16_end:
;Don't mess with flags hereafter!
pop dx
pop cx
pop bx
pop ds
mov sp, bp
pop bp
ret
CR_CHAR EQU 0dh
NASM 移植
要将代码移植到 NASM,请从内存访问中删除 PTR
关键字(例如,mov cl, BYTE PTR [si]
变为 mov cl, BYTE [si]
)