Assembly Language Debugging Routine, Study notes of Microprocessor and Assembly Language Programming

An assembly language program that serves as a basic debugger using breakpoint interrupts and keyboard inputs. It includes a keyboard interrupt service routine (kbisr), a single-step interrupt service routine (trapisr), and a breakpoint interrupt service routine (debugisr). The program also demonstrates how to set and clear breakpoints using int3 and how to display and manipulate register values.

Typology: Study notes

2011/2012

Uploaded on 08/04/2012

saqqi
saqqi 🇵🇰

4

(33)

40 documents

1 / 5

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
push dx
push di
mov di, 80 ; load di with columns per row
mov ax, [bp+8] ; load ax with row number
mul di ; multiply with columns per row
mov di, ax ; save result in di
add di, [bp+6] ; add column number
shl di, 1 ; turn into byte count
add di, 8 ; to end of number location
mov ax, 0xb800
mov es, ax ; point es to video base
mov ax, [bp+4] ; load number in ax
mov bx, 16 ; use base 16 for division
mov cx, 4 ; initialize count of digits
nextdigit: mov dx, 0 ; zero upper half of dividend
div bx ; divide by 10
add dl, 0x30 ; convert digit into ascii value
cmp dl, 0x39 ; is the digit an alphabet
jbe skipalpha ; no, skip addition
add dl, 7 ; yes, make in alphabet code
skipalpha: mov dh, 0x07 ; attach normal attribute
mov [es:di], dx ; print char on screen
sub di, 2 ; to previous screen location
loop nextdigit ; if no divide it again
pop di
pop dx
pop cx
pop bx
pop ax
pop es
pop bp
ret 6
; subroutine to print a string
; takes row no, column no, address of string, and its length
; as parameters
printstr: push bp
mov bp, sp
push es
push ax
push bx
push cx
push dx
push si
push di
mov ax, 0xb800
mov es, ax ; point es to video base
mov di, 80 ; load di with columns per row
mov ax, [bp+10] ; load ax with row number
mul di ; multiply with columns per row
mov di, ax ; save result in di
add di, [bp+8] ; add column number
shl di, 1 ; turn into byte count
mov si, [bp+6] ; string to be printed
mov cx, [bp+4] ; length of string
mov ah, 0x07 ; normal attribute is fixed
nextchar: mov al, [si] ; load next char of string
mov [es:di], ax ; show next char on screen
add di, 2 ; move to next screen location
add si, 1 ; move to next char
loop nextchar ; repeat the operation cx times
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pf3
pf4
pf5

Partial preview of the text

Download Assembly Language Debugging Routine and more Study notes Microprocessor and Assembly Language Programming in PDF only on Docsity!

push dx push di

mov di, 80 ; load di with columns per row mov ax, [bp+8] ; load ax with row number mul di ; multiply with columns per row mov di, ax ; save result in di add di, [bp+6] ; add column number shl di, 1 ; turn into byte count add di, 8 ; to end of number location

mov ax, 0xb mov es, ax ; point es to video base mov ax, [bp+4] ; load number in ax mov bx, 16 ; use base 16 for division mov cx, 4 ; initialize count of digits

nextdigit: mov dx, 0 ; zero upper half of dividend div bx ; divide by 10 add dl, 0x30 ; convert digit into ascii value cmp dl, 0x39 ; is the digit an alphabet jbe skipalpha ; no, skip addition add dl, 7 ; yes, make in alphabet code skipalpha: mov dh, 0x07 ; attach normal attribute mov [es:di], dx ; print char on screen sub di, 2 ; to previous screen location loop nextdigit ; if no divide it again

pop di pop dx pop cx pop bx pop ax pop es pop bp ret 6

; subroutine to print a string ; takes row no, column no, address of string, and its length ; as parameters printstr: push bp mov bp, sp push es push ax push bx push cx push dx push si push di

mov ax, 0xb mov es, ax ; point es to video base

mov di, 80 ; load di with columns per row mov ax, [bp+ 10 ] ; load ax with row number mul di ; multiply with columns per row mov di, ax ; save result in di add di, [bp+ 8 ] ; add column number shl di, 1 ; turn into byte count

mov si, [bp+6] ; string to be printed mov cx, [bp+4] ; length of string mov ah, 0x07 ; normal attribute is fixed

nextchar: mov al, [si] ; load next char of string mov [es:di], ax ; show next char on screen add di, 2 ; move to next screen location add si, 1 ; move to next char loop nextchar ; repeat the operation cx times

pop di pop si pop dx pop cx pop bx pop ax

pop es pop bp ret 8

; keyboard interrupt service routine kbisr: push ax

in al, 0x60 ; read a char from keyboard port test al, 0x80 ; is it a press code jnz skipflag ; no, leave the interrupt add byte [cs:flag], al ; yes, set flag to proceed

skipflag: mov al, 0x out 0x20, al pop ax iret

; single step interrupt service routine trapisr: push bp mov bp, sp ; to read cs, ip and flags push ax push bx push cx push dx push si push di push ds push es

sti ; waiting for keyboard interrupt push cs pop ds ; initialize ds to data segment

mov byte [flag], 0 ; set flag to wait for key call clrscr ; clear the screen

mov si, 6 ; first register is at bp+ mov cx, 12 ; total 12 registers to print mov ax, 0 ; start from row 0 mov bx, 5 ; print at column 5

l3: push ax ; row number push bx ; column number mov dx, [bp+si] push dx ; number to be printed call printnum ; print the number sub si, 2 ; point to next register inc ax ; next row number loop l3 ; repeat for the 12 registers

mov ax, 0 ; start from row 0 mov bx, 0 ; start from column 0 mov cx, 12 ; total 12 register names mov si, 4 ; each name length is 4 chars mov dx, names ; offset of first name in dx

l1: push ax ; row number push bx ; column number push dx ; offset of string push si ; length of string call printstr ; print the string add dx, 4 ; point to start of next string inc ax ; new row number loop l1 ; repeat for 12 register names

keywait: cmp byte [flag], 0 ; has a key been pressed je keywait ; no, check again

pop es pop ds pop di pop si pop dx pop cx pop bx pop ax

mov ax, [bp+4] mov es, ax ; load interrupted segment in es mov di, [opcodepos] ; load saved opcode position mov byte [es:di], 0xCC ; reset the opcode to INT and word [bp+6], 0xFEFF; clear TF in flags on stack

pop es pop ds pop di pop ax pop bp iret

; breakpoint interrupt service routine debugisr: push bp mov bp, sp ; to read cs, ip and flags push ax push bx push cx push dx push si push di push ds push es

sti ; waiting for keyboard interrupt push cs pop ds ; initialize ds to data segment

mov ax, [bp+4] mov es, ax ; load interrupted segment in es dec word [bp+2] ; decrement the return address mov di, [bp+2] ; read the return address in di mov word [opcodepos], di ; remember the return position mov al, [opcode] ; load the original opcode mov [es:di], al ; restore original opcode there

mov byte [flag], 0 ; set flag to wait for key call clrscr ; clear the screen

mov si, 6 ; first register is at bp+ mov cx, 12 ; total 12 registers to print mov ax, 0 ; start from row 0 mov bx, 5 ; print at column 5

l3: push ax ; row number push bx ; column number mov dx, [bp+si] push dx ; number to be printed call printnum ; print the number sub si, 2 ; point to next register inc ax ; next row number loop l3 ; repeat for the 12 registers

mov ax, 0 ; start from row 0 mov bx, 0 ; start from column 0 mov cx, 12 ; total 12 register names mov si, 4 ; each name length is 4 chars mov dx, names ; offset of first name in dx

l1: push ax ; row number push bx ; column number push dx ; offset of string push si ; length of string call printstr ; print the string add dx, 4 ; point to start of next string inc ax ; new row number loop l1 ; repeat for 12 register names

or word [bp+6], 0x0100 ; set TF in flags image on stack

keywait: cmp byte [flag], 0 ; has a key been pressed je keywait ; no, check again

pop es

pop ds pop di pop si pop dx pop cx pop bx pop ax pop bp iret

start: xor ax, ax mov es, ax ; point es to IVT base mov word [es:14], trapisr ; store offset at n mov [es:14+2], cs ; store segment at n4+ mov word [es:34], debugisr ; store offset at n mov [es:34+2], cs ; store segment at n4+ cli ; disable interrupts mov word [es:94], kbisr ; store offset at n mov [es:94+2], cs ; store segment at n4+ sti ; enable interrupts

mov si, l2 ; load breakpoint position in si mov al, [cs:si] ; read opcode at that position mov [opcode], al ; save opcode for later use mov byte [cs:si], 0xCC ; change opcode to INT

; breakpoint is set now, INT3 will come at l2 on every iteration ; sample code to check the working of our elementary debugger mov ax, 0 mov bx, 0x mov cx, 0x mov dx, 0x

l2: inc ax add bx, 2 dec cx sub dx, 2 jmp l