📄 irvine16.asm
字号:
TITLE Link Library Functions (Irvine16.asm)
Comment @
This library was created exlusively for use with the book,
"Assembly Language for Intel-Based Computers, 4th Edition",
by Kip R. Irvine, 2002.
Copyright 2002, Prentice-Hall Incorporated. No part of this file may be
reproduced, in any form or by any other means, without permission in writing
from the publisher.
Updates to this file will be posted at the book's site:
www.nuvisionmiami.com/books/asm
Acknowledgements:
------------------------------
Most of the code in this library was written by Kip Irvine.
Special thanks to Gerald Cahill for his many insights, suggestions, and bug fixes!
Also to Courtney Amor, a student at UCLA.
Alphabetical Listing of Procedures
----------------------------------
(Unless otherwise marked, all procedures are documented in Chapter 5.)
ClrScr
Crlf
Delay
DumpMem
DumpRegs
GetCommandTail
GetDateTime Chapter 11
GetMseconds
Gotoxy
IsDigit
Random32
Randomize
RandomRange
ReadChar
ReadHex
ReadInt
ReadString
SetTextColor
Str_compare Chapter 9
Str_copy Chapter 9
Str_length Chapter 9
Str_trim Chapter 9
Str_ucase Chapter 9
WaitMsg
WriteBin
WriteChar
WriteDec
WriteHex
WriteInt
WriteString
=================================@
INCLUDE Irvine16.inc
; Write <count< spaces to standard output
WriteSpace MACRO count
Local spaces
.data
spaces BYTE count dup(' '),0
.code
mov dx,OFFSET spaces
call WriteString
ENDM
; Send a newline sequence to standard output
NewLine MACRO
Local temp
.data
temp BYTE 13,10,0
.code
push dx
mov dx,OFFSET temp
call WriteString
pop dx
ENDM
;-------------------------------------
ShowRegister MACRO regName, regVal
Local str
;
; Show a single register value
;-------------------------------------
.data
str BYTE " ®Name=",0
.code
push eax
push edx ; save EDX
mov dx,OFFSET str
call WriteString
pop edx ; must restore EDX now
IF (TYPE regVal) EQ 4
mov eax,regVal ; register value
ELSE
mov eax,0
mov ax,regVal
ENDIF
call WriteHex
pop eax
ENDM
;-------------------------------------
ShowFlag MACRO flagName,shiftCount
LOCAL flagStr, flagVal, L1
;
; Display a single flag value
;-------------------------------------
.data
flagStr BYTE " &flagName="
flagVal BYTE ?,0
.code
push ax
push dx
mov ax,flags ; retrieve the flags
mov flagVal,'1'
shr ax,shiftCount ; shift into carry flag
jc L1
mov flagVal,'0'
L1:
mov dx,OFFSET flagStr ; display flag name and value
call WriteString
pop dx
pop ax
ENDM
;--------- END OF MACRO DEFINITIONS ---------------------------
;********************* SHARED DATA AREA **********************
.data?
buffer BYTE 512 dup(?)
;*************************************************************
.code
;------------------------------------------------------
Clrscr PROC
;
; Clears the screen (video page 0) and locates the cursor
; at row 0, column 0.
; Receives: nothing
; Returns: nothing
;-------------------------------------------------------
pusha
mov ax,0600h ; scroll window up
mov cx,0 ; upper left corner (0,0)
mov dx,184Fh ; lower right corner (24,79)
mov bh,7 ; normal attribute
int 10h ; call BIOS
mov ah,2 ; locate cursor at 0,0
mov bh,0 ; video page 0
mov dx,0 ; row 0, column 0
int 10h
popa
ret
Clrscr ENDP
;-----------------------------------------------------
Crlf PROC
;
; Writes a carriage return / linefeed
; sequence (0Dh,0Ah) to standard output.
;-----------------------------------------------------
NewLine ; invoke a macro
ret
Crlf ENDP
;-----------------------------------------------------------
Delay PROC
;
; Create an n-millisecond delay.
; Receives: EAX = milliseconds
; Returns: nothing
; Remarks: May only used under Windows 95, 98, or ME. Does
; not work under Windows NT, 2000, or XP, because it
; directly accesses hardware ports.
; Source: "The 80x86 IBM PC & Compatible Computers" by
; Mazidi and Mazidi, page 343. Prentice-Hall, 1995.
;-----------------------------------------------------------
MsToMicro = 1000000 ; convert ms to microseconds
ClockFrequency = 15085 ; microseconds per tick
.code
pushad
; Convert milliseconds to microseconds.
mov ebx,MsToMicro
mul ebx
; Divide by clock frequency of 15.085 microseconds,
; producing the counter for port 61h.
mov ebx,ClockFrequency
div ebx ; eax = counter
mov ecx,eax
; Begin checking port 61h, watching bit 4 toggle
; between 1 and 0 every 15.085 microseconds.
L1:
in al,61h ; read port 61h
and al,10h ; clear all bits except bit 4
cmp al,ah ; has it changed?
je L1 ; no: try again
mov ah,al ; yes: save status
dec ecx
cmp ecx,0 ; loop finished yet?
ja L1
quit:
popad
ret
Delay ENDP
;---------------------------------------------------
DumpMem PROC
LOCAL unitsize:word, byteCount:word
;
; Writes a range of memory to standard output
; in hexadecimal.
; Receives: SI = starting OFFSET, CX = number of units,
; BX = unit size (1=byte, 2=word, or 4=doubleword)
; Returns: nothing
;---------------------------------------------------
.data
oneSpace BYTE ' ',0
dumpPrompt BYTE 13,10,"Dump of offset ",0
.code
pushad
mov dx,OFFSET dumpPrompt
call WriteString
movzx eax,si
call WriteHex
NewLine
mov byteCount,0
mov unitsize,bx
cmp bx,4 ; select output size
je L1
cmp bx,2
je L2
jmp L3
L1: ; doubleword output
mov eax,[si]
call WriteHex
WriteSpace 2
add si,bx
Loop L1
jmp L4
L2: ; word output
mov ax,[si] ; get a word from memory
ror ax,8 ; display high byte
call HexByte
ror ax,8 ; display low byte
call HexByte
WriteSpace 1 ; display 1 space
add si,unitsize ; point to next word
Loop L2
jmp L4
; Byte output: 16 bytes per line
L3:
mov al,[si]
call HexByte
inc byteCount
WriteSpace 1
inc si
; if( byteCount mod 16 == 0 ) call Crlf
mov dx,0
mov ax,byteCount
mov bx,16
div bx
cmp dx,0
jne L3B
NewLine
L3B:
Loop L3
jmp L4
L4:
NewLine
popad
ret
DumpMem ENDP
;--------------------------------------------------
Get_Commandtail PROC
;
; Gets a copy of the DOS command tail at PSP:80h.
; Receives: DX contains the offset of the buffer
; that receives a copy of the command tail.
; Returns: CF=1 if the buffer is empty; otherwise,
; CF=0.
; Last update: 11/11/01
;--------------------------------------------------
push es
pusha ; save general registers
mov ah,62h ; get PSP segment address
int 21h ; returned in BX
mov es,bx ; copied to ES
mov si,dx ; point to buffer
mov di,81h ; PSP offset of command tail
mov cx,0 ; byte count
mov cl,es:[di-1] ; get length byte
cmp cx,0 ; is the tail empty?
je L2 ; yes: exit
cld ; no: scan forward
mov al,20h ; space character
repz scasb ; scan for non space
jz L2 ; all spaces found
dec di ; non space found
inc cx
L1: mov al,es:[di] ; copy tail to buffer
mov [si],al ; pointed to by DS:SI
inc si
inc di
loop L1
clc ; CF=0 means tail found
jmp L3
L2: stc ; set carry: no command tail
L3: mov byte ptr [si],0 ; store null byte
popa ; restore registers
pop es
ret
Get_Commandtail ENDP
;---------------------------------------------------
Gotoxy PROC
;
; Sets the cursor position on video page 0.
; display page.
; Receives: DH,DL = row, column
; Returns: nothing
;---------------------------------------------------
pusha
mov ah,2
mov bh,0
int 10h
popa
ret
Gotoxy ENDP
HexByte PROC
LOCAL theByte:BYTE
; Display the byte in AL in hexadecimal
; Called only by DumpMem. Updated 9/21/01
pusha
mov theByte,al ; save the byte
mov cx,2
HB1:
rol theByte,4
mov al,theByte
and al,0Fh
mov bx,OFFSET xtable
xlat
; insert hex char in the buffer
; and display using WriteString
mov buffer,al
mov [buffer+1],0
mov dx,OFFSET buffer
call WriteString
Loop HB1
popa
ret
HexByte ENDP
;---------------------------------------------------
DumpRegs PROC
;
; Displays EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP in
; hexadecimal. Also displays the Zero, Sign, Carry, and
; Overflow flags.
; Receives: nothing.
; Returns: nothing.
;
; Warning: do not create any local variables or stack
; parameters, because they will alter the EBP register.
;---------------------------------------------------
.data
flags WORD ?
saveIP WORD ?
saveSP WORD ?
.code
pop saveIP ; get current IP
mov saveSP,sp ; save SP's value at entry
push saveIP ; replace it on stack
push eax
pushfd ; push flags
pushf ; copy flags to a variable
pop flags
NewLine
ShowRegister EAX,EAX
ShowRegister EBX,EBX
ShowRegister ECX,ECX
ShowRegister EDX,EDX
NewLine
ShowRegister ESI,ESI
ShowRegister EDI,EDI
ShowRegister EBP,EBP
movzx eax,saveSP
ShowRegister ESP,EAX
NewLine
movzx eax,saveIP
ShowRegister EIP,EAX
movzx eax,flags
ShowRegister EFL,EAX
; Show the flags
ShowFlag CF,1
ShowFlag SF,8
ShowFlag ZF,7
ShowFlag OF,12
NewLine
NewLine
popfd ; restore flags
pop eax ; restore EAX
ret
DumpRegs ENDP
;---------------------------------------------------
Get_time PROC
;
; Get the current system time.Input parameter:
; DS:SI points to a TimeRecord structure.
; PRIVATE FUNCTION
;---------------------------------------------------
pushad
mov ah,2Ch
int 21h
mov (TimeRecord ptr [si]).hours,ch
mov (TimeRecord ptr [si]).minutes,cl
mov (TimeRecord ptr [si]).seconds,dh
mov (TimeRecord ptr [si]).hhss,dl
popad
ret
Get_time ENDP
;-----------------------------------------------
Isdigit PROC
;
; Determines whether the character in AL is a
; valid decimal digit.
; Receives: AL = character
; Returns: ZF=1 if AL contains a valid decimal
; digit; otherwise, ZF=0.
;-----------------------------------------------
cmp al,'0'
jb ID1
cmp al,'9'
ja ID1
test ax,0 ; set ZF = 1
ID1: ret
Isdigit ENDP
;--------------------------------------------------------------
RandomRange PROC
;
; Returns an unsigned pseudo-random 32-bit integer
; in EAX, between 0 and n-1. Input parameter:
; EAX = n.
;--------------------------------------------------------------
push bp
mov bp,sp
push ebx
push edx
mov ebx,eax ; maximum value
call Random32 ; eax = random number
mov edx,0
div ebx ; divide by max value
mov eax,edx ; return the remainder
pop edx
pop ebx
pop bp
ret
RandomRange ENDP
;--------------------------------------------------------------
Random32 PROC
;
; Returns an unsigned pseudo-random 32-bit integer
; in EAX,in the range 0 - FFFFFFFFh.
;--------------------------------------------------------------
.data
seed dd 1
.code
push edx
mov eax, 343FDh
imul seed
add eax, 269EC3h
mov seed, eax ; save the seed for the next call
ror eax,8 ; rotate out the lowest digit (10/22/00)
pop edx
ret
Random32 ENDP
;--------------------------------------------------------
Randomize PROC
;
; Re-seeds the random number generator with the current time
; in seconds.
;
;--------------------------------------------------------
push eax
call Seconds_today
mov seed,eax
pop eax
ret
Randomize ENDP
;---------------------------------------------------------
ReadChar PROC
;
; Reads one character from standard input and echoes
; on the screen. Waits for the character if none is
; currently in the input buffer.
; Receives: nothing
; Returns: AL = ASCII code
;----------------------------------------------------------
mov ah,1
int 21h
ret
ReadChar ENDP
;--------------------------------------------------------
ReadHex PROC
;
; Reads a 32-bit hexadecimal integer from standard input,
; stopping when the Enter key is pressed.
; Receives: nothing
; Returns: EAX = binary integer value
; Remarks: No error checking performed for bad digits
; or excess digits.
; Last update: 11/7/01
;--------------------------------------------------------
.data
HMAX_DIGITS = 128
Hinputarea BYTE HMAX_DIGITS dup(0),0
xbtable BYTE 0,1,2,3,4,5,6,7,8,9,7 DUP(0FFh),10,11,12,13,14,15
numVal DWORD ?
charVal BYTE ?
.code
push ebx
push ecx
push edx
push esi
mov edx,OFFSET Hinputarea
mov esi,edx ; save in ESI also
mov ecx,HMAX_DIGITS
call ReadString ; input the string
mov ecx,eax ; save length in ECX
; Start to convert the number.
B4: mov numVal,0 ; clear accumulator
mov ebx,OFFSET xbtable ; translate table
; Repeat loop for each digit.
B5: mov al,[esi] ; get character from buffer
cmp al,'F' ; lowercase letter?
jbe B6 ; no
and al,11011111b ; yes: convert to uppercase
B6:
sub al,30h ; adjust for table
xlat ; translate to binary
mov charVal,al
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -