📄 irvine16.asm
字号:
mov eax,16 ; numVal *= 16
mul numVal
mov numVal,eax
movzx eax,charVal ; numVal += charVal
add numVal,eax
inc esi ; point to next digit
loop B5 ; repeat, decrement counter
mov eax,numVal ; return binary result
pop esi
pop edx
pop ecx
pop ebx
ret
ReadHex ENDP
;--------------------------------------------------------
ReadInt PROC uses ebx ecx edx esi
LOCAL Lsign:DWORD, saveDigit:DWORD
;
; Reads a 32-bit signed decimal integer from standard
; input, stopping when the Enter key is pressed.
; All valid digits occurring before a non-numeric character
; are converted to the integer value. Leading spaces are
; ignored, and an optional leading + or - sign is permitted.
; Receives: nothing
; Returns: If CF=0, the integer is valid, and EAX = binary value.
; If CF=1, the integer is invalid and EAX = 0.
;
; Credits: Thanks to Courtney Amor, a student at the UCLA Mathematics
; department, for pointing out improvements that have been
; implemented in this version.
; Last update: 1/27/02
;--------------------------------------------------------
.data
LMAX_DIGITS = 80
Linputarea BYTE LMAX_DIGITS dup(0),0
overflow_msgL BYTE " <32-bit integer overflow>",0
invalid_msgL BYTE " <invalid integer>",0
.code
; Input a string of digits using ReadString.
mov edx,offset Linputarea
mov esi,edx ; save offset in ESI
mov ecx,LMAX_DIGITS
call ReadString
mov ecx,eax ; save length in CX
mov Lsign,1 ; assume number is positive
cmp ecx,0 ; greater than zero?
jne L1 ; yes: continue
mov eax,0 ; no: set return value
jmp L10 ; and exit
; Skip over any leading spaces.
L1: mov al,[esi] ; get a character from buffer
cmp al,' ' ; space character found?
jne L2 ; no: check for a sign
inc esi ; yes: point to next char
loop L1
jcxz L8 ; quit if all spaces
; Check for a leading sign.
L2: cmp al,'-' ; minus sign found?
jne L3 ; no: look for plus sign
mov Lsign,-1 ; yes: sign is negative
dec ecx ; subtract from counter
inc esi ; point to next char
jmp L4
L3: cmp al,'+' ; plus sign found?
jne L4 ; no: must be a digit
inc esi ; yes: skip over the sign
dec ecx ; subtract from counter
; Test the first digit, and exit if it is nonnumeric.
L3A:mov al,[esi] ; get first character
call IsDigit ; is it a digit?
jnz L7A ; no: show error message
; Start to convert the number.
L4: mov eax,0 ; clear accumulator
mov ebx,10 ; EBX is the divisor
; Repeat loop for each digit.
L5: mov dl,[esi] ; get character from buffer
cmp dl,'0' ; character < '0'?
jb L9
cmp dl,'9' ; character > '9'?
ja L9
and edx,0Fh ; no: convert to binary
mov saveDigit,edx
imul ebx ; EDX:EAX = EAX * EBX
mov edx,saveDigit
jo L6 ; quit if overflow
add eax,edx ; add new digit to AX
jo L6 ; quit if overflow
inc esi ; point to next digit
jmp L5 ; get next digit
; Overflow has occured, unlesss EAX = 80000000h
; and the sign is negative:
L6: cmp eax,80000000h
jne L7
cmp Lsign,-1
jne L7 ; overflow occurred
jmp L9 ; the integer is valid
; Choose "integer overflow" messsage.
L7: mov edx,OFFSET overflow_msgL
jmp L8
; Choose "invalid integer" message.
L7A:
mov edx,OFFSET invalid_msgL
; Display the error message pointed to by EDX.
L8: call WriteString
call Crlf
stc ; set Carry flag
mov eax,0 ; set return value to zero
jmp L10 ; and exit
L9: imul Lsign ; EAX = EAX * sign
L10:ret
ReadInt ENDP
;--------------------------------------------------------
ReadString PROC
; Reads a string from standard input and places the
; characters in a buffer. Reads past end of line,
; and removes the CF/LF from the string.
; Receives: DS:DX points to the input buffer,
; CX = maximum characters that may be typed.
; Returns: AX = size of the input string.
; Comments: Stops when the Enter key (0Dh) is pressed.
;--------------------------------------------------------
push cx ; save registers
push si
push cx ; save digit count again
mov si,dx ; point to input buffer
L1: mov ah,1 ; function: keyboard input
int 21h ; DOS returns char in AL
cmp al,0Dh ; end of line?
je L2 ; yes: exit
mov [si],al ; no: store the character
inc si ; increment buffer pointer
loop L1 ; loop until CX=0
L2: mov byte ptr [si],0 ; end with a null byte
pop ax ; original digit count
sub ax,cx ; AX = size of input string
pop si ; restore registers
pop cx
ret
ReadString ENDP
;-------------------------------------------------------
Seconds_today PROC
;
; Returns a count of the number of seconds that
; have elapsed today. Output: EAX contains the
; return value. Range: 0 - 86,399
;--------------------------------------------------------
.data
timerec TimeRecord <>
saveSec DWORD ?
.code
push ebx
push si
mov si,OFFSET timerec
call Get_time
; calculate # seconds based on hours.
xor eax,eax
mov al,(TimeRecord ptr [si]).hours
mov ebx,3600
mul ebx
mov saveSec,eax
; multiply minutes by 60
xor eax,eax
mov al,(TimeRecord ptr [si]).minutes
mov ebx,60
mul ebx
add saveSec,eax
xor eax,eax
mov al,(TimeRecord ptr [si]).seconds
add eax,saveSec
pop si
pop ebx
ret
Seconds_today ENDP
;----------------------------------------------------------
Str_compare PROC USES ax dx si di,
string1:PTR BYTE,
string2:PTR BYTE
;
; Compare two strings.
; Returns nothing, but the Zero and Carry flags are affected
; exactly as they would be by the CMP instruction.
; Last update: 1/18/02
;-----------------------------------------------------
mov si,string1
mov di,string2
L1: mov al,[si]
mov dl,[di]
cmp al,0 ; end of string1?
jne L2 ; no
cmp dl,0 ; yes: end of string2?
jne L2 ; no
jmp L3 ; yes, exit with ZF = 1
L2: inc si ; point to next
inc di
cmp al,dl ; chars equal?
je L1 ; yes: continue loop
; no: exit with flags set
L3: ret
Str_compare ENDP
;---------------------------------------------------------
Str_copy PROC USES ax cx si di,
source:PTR BYTE, ; source string
target:PTR BYTE ; target string
;
; Copy a string from source to target.
; Requires: the target string must contain enough
; space to hold a copy of the source string.
; Last update: 1/18/02
;----------------------------------------------------------
INVOKE Str_length,source ; AX = length source
mov cx,ax ; REP count
inc cx ; add 1 for null byte
mov si,source
mov di,target
cld ; direction = up
rep movsb ; copy the string
ret
Str_copy ENDP
;---------------------------------------------------------
Str_length PROC USES di,
pString:PTR BYTE ; pointer to string
;
; Return the length of a null-terminated string.
; Receives: pString - pointer to a string
; Returns: AX = string length
; Last update: 1/18/02
;---------------------------------------------------------
mov di,pString
mov ax,0 ; character count
L1:
cmp byte ptr [di],0 ; end of string?
je L2 ; yes: quit
inc di ; no: point to next
inc ax ; add 1 to count
jmp L1
L2: ret
Str_length ENDP
;-----------------------------------------------------------
Str_trim PROC USES ax cx di,
pString:PTR BYTE, ; points to string
char:BYTE ; char to remove
;
; Remove all occurences of a given character from
; the end of a string.
; Returns: nothing
; Last update: 1/18/02
;-----------------------------------------------------------
mov di,pString
INVOKE Str_length,di ; returns length in AX
cmp ax,0 ; zero-length string?
je L2 ; yes: exit
mov cx,ax ; no: counter = string length
dec ax
add di,ax ; DI points to last char
mov al,char ; char to trim
std ; direction = reverse
repe scasb ; skip past trim character
jne L1 ; removed first character?
dec di ; adjust DI: ZF=1 && ECX=0
L1: mov BYTE PTR [di+2],0 ; insert null byte
L2: ret
Str_trim ENDP
;---------------------------------------------------
Str_ucase PROC USES ax si,
pString:PTR BYTE
; Convert a null-terminated string to upper case.
; Receives: pString - a pointer to the string
; Returns: nothing
; Last update: 1/18/02
;---------------------------------------------------
mov si,pString
L1:
mov al,[si] ; get char
cmp al,0 ; end of string?
je L3 ; yes: quit
cmp al,'a' ; below "a"?
jb L2
cmp al,'z' ; above "z"?
ja L2
and BYTE PTR [si],11011111b ; convert the char
L2: inc si ; next char
jmp L1
L3: ret
Str_ucase ENDP
;------------------------------------------------------
WaitMsg PROC
;
; Displays "Press any key to continue"
; Receives: nothing
; Returns: nothing
;------------------------------------------------------
.data
waitmsgstr BYTE "Press any key to continue...",0
.code
push dx
mov dx,OFFSET waitmsgstr
call WriteString
call ReadChar
NewLine
pop dx
ret
WaitMsg ENDP
;------------------------------------------------------
WriteBin PROC
;
; Writes a 32-bit integer to standard output in
; binary format.
; Receives: EAX = the integer to write
;------------------------------------------------------
.code
push eax
push ecx
push edx
mov cx,32 ; number of bits in AX
mov si,OFFSET buffer
WB1:
shl eax,1 ; shift EAX left into Carry flag
mov byte ptr [si],'0' ; choose '0' as default digit
jnc WB2 ; if no carry, then jump to L2
mov byte ptr [si],'1' ; else move '1' to DL
WB2:
inc si
loop WB1 ; shift another bit to left
mov byte ptr [si],0 ; insert null byte at end
mov dx,OFFSET buffer ; display the buffer
call WriteString
pop edx
pop ecx
pop eax
ret
WriteBin ENDP
;------------------------------------------------------
WriteChar PROC
;
; Write a character to standard output
; Recevies: AL = character
;------------------------------------------------------
push ax
push dx
mov ah,2
mov dl,al
int 21h
pop dx
pop ax
ret
WriteChar ENDP
;-----------------------------------------------------
WriteDec PROC
;
; Writes an unsigned 32-bit decimal number to
; standard output. Input parameters: EAX = the
; number to write.
;
;------------------------------------------------------
.data
; There will be as many as 10 digits.
BUFFER_SIZE = 12
bufferL BYTE BUFFER_SIZE dup(?),0
xtable BYTE "0123456789ABCDEF"
.code
pushad ; save all 32-bit data registers
mov cx,0 ; digit counter
mov di,OFFSET bufferL
add di,(BUFFER_SIZE - 1)
mov ebx,10 ; decimal number base
WI1:
mov edx,0 ; clear dividend to zero
div ebx ; divide EAX by the radix
xchg eax,edx ; swap quotient, remainder
call AsciiDigit ; convert AL to ASCII
mov [di],al ; save the digit
dec di ; back up in buffer
xchg eax,edx ; swap quotient, remainder
inc cx ; increment digit count
or eax,eax ; quotient = 0?
jnz WI1 ; no, divide again
; Display the digits (CX = count)
WI3:
inc di
mov dx,di
call WriteString
WI4:
popad ; restore 32-bit registers
ret
WriteDec ENDP
; Convert AL to an ASCII digit.
AsciiDigit PROC private
push bx
mov bx,OFFSET xtable
xlat
pop bx
ret
AsciiDigit ENDP
;------------------------------------------------------
WriteHex PROC
;
; Writes an unsigned 32-bit hexadecimal number to
; standard output.
; Input parameters: EAX = the number to write.
;
;------------------------------------------------------
DISPLAY_SIZE = 8 ; total number of digits to display
.data
bufferLH BYTE DISPLAY_SIZE dup(?),0
.code
pushad ; save all 32-bit data registers
mov cx,0 ; digit counter
mov di,OFFSET bufferLH
add di,(DISPLAY_SIZE - 1)
mov ebx,16 ; hexadecimal base
WLH1:
mov edx,0 ; clear dividend to zero
div ebx ; divide EAX by the radix
xchg eax,edx ; swap quotient, remainder
call AsciiDigit ; convert AL to ASCII
mov [di],al ; save the digit
dec di ; back up in buffer
xchg eax,edx ; swap quotient, remainder
inc cx ; increment digit count
or eax,eax ; quotient = 0?
jnz WLH1 ; no, divide again
; Insert leading zeros
mov ax,DISPLAY_SIZE
sub ax,cx
jz WLH3 ; display now if no leading zeros required
mov cx,ax ; CX = number of leading zeros to insert
WLH2:
mov byte ptr [di],'0' ; insert a zero
dec di ; back up
loop WLH2 ; continue the loop
; Display the digits
WLH3:
mov cx,DISPLAY_SIZE
inc di
mov dx,di
call WriteString
popad ; restore 32-bit registers
ret
WriteHex ENDP
;-----------------------------------------------------
WriteInt PROC
;
; Writes a 32-bit signed binary integer to standard output
; in ASCII decimal.
; Receives: EAX = the integer
; Returns: nothing
; Comments: Displays a leading sign, no leading zeros.
;-----------------------------------------------------
WI_Bufsize = 12
true = 1
false = 0
.data
buffer_B BYTE WI_Bufsize dup(0),0 ; buffer to hold digits
neg_flag BYTE ?
.code
pushad
mov neg_flag,false ; assume neg_flag is false
or eax,eax ; is AX positive?
jns WIS1 ; yes: jump to B1
neg eax ; no: make it positive
mov neg_flag,true ; set neg_flag to true
WIS1:
mov cx,0 ; digit count = 0
mov di,OFFSET buffer_B
add di,(WI_Bufsize-1)
mov ebx,10 ; will divide by 10
WIS2:
mov edx,0 ; set dividend to 0
div ebx ; divide AX by 10
or dl,30h ; convert remainder to ASCII
dec di ; reverse through the buffer
mov [di],dl ; store ASCII digit
inc cx ; increment digit count
or eax,eax ; quotient > 0?
jnz WIS2 ; yes: divide again
; Insert the sign.
dec di ; back up in the buffer
inc cx ; increment counter
mov byte ptr [di],'+' ; insert plus sign
cmp neg_flag,false ; was the number positive?
jz WIS3 ; yes
mov byte ptr [di],'-' ; no: insert negative sign
WIS3: ; Display the number
mov dx,di
call WriteString
popad
ret
WriteInt ENDP
;--------------------------------------------------------
WriteString PROC
; Writes a null-terminated string to standard output
; Receives: DS:DX points to the string
; Returns: nothing
;--------------------------------------------------------
pusha
push ds ; set ES to DS
pop es
mov di,dx ; ES:DI = string ptr
INVOKE Str_length, DX ; AX = string length
mov cx,ax ; CX = number of bytes
mov ah,40h ; write to file or device
mov bx,1 ; standard output handle
int 21h ; call MS-DOS
popa
ret
WriteString ENDP
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -