Multitasking and Debugging-Microprocessor and Assembly Language Programming-Lecture Notes, Study notes of Microprocessor and Assembly Language Programming

This lecture handout was provided at Quaid-i-Azam University for Microprocessor and Assembly Language Programming course by Prof. Saleem Raza. Its main points are: Multitasling, Impliment, Debugging, Kernel, Tsr, Stack, Registers, Language, Assembly, Breaking, Restoring

Typology: Study notes

2011/2012

Uploaded on 08/04/2012

saqqi
saqqi ๐Ÿ‡ต๐Ÿ‡ฐ

4

(33)

40 documents

1 / 8

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
To experience the power of assembly language we introduce how to
implement multitasking. We observed in the debugger that our thread of
instructions was broken by the debugger; it got the control, used all
registers, displayed an elaborate interface, waited for the key, and then
restored processor state to what was immediately before interruption. Our
program resumed as if nothing happened. The program execution was in the
same logical flow.
If we have two different programs A and B. Program A is broken, its state
saved, and returned to B instead of A. By looking at the instruction set, we
can immediately say that nothing can stop us from doing that. IRET will
return to whatever CS and IP it finds on the stack. Now B is interrupted
somehow, its state saved, and we return back to A. A will have no way of
knowing that it was interrupted as its entire environment has been restored.
It never knew the debugger took control when it was debugged. It sill has no
way of gaining this knowledge. If this work of breaking and restoring
programs is done at high speed the user will feel that all the programs are
running at the same time where actually they are being switched to and forth
at high speed.
In essence multitasking is simple, even though we have to be extremely
careful when implementing it. The environment of a program in the very
simple case is all its registers and stack. We will deal with stack later. Now to
get control from the program without the program knowing about it, we can
use the IRQ 0 highest priority interrupt that is periodically coming to the
processor.
Now we present a very basic example of multitasking. We have two
subroutines written in assembly language. All the techniques discussed here
are applicable to code written in higher level languages as well. However the
code to control this multitasking cannot be easily written in a higher level
language so we write it in assembly language. The two subroutines rotate
bars by changing characters at the two corners of the screen and have
infinite loops. By hooking the timer interrupt and saving and restoring the
registers of the tasks one by one, it appears that both tasks are running
simultaneously.
Example
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
; elementary multitasking of two threads
[org 0x0100]
jmp start
; ax,bx,ip,cs,flags storage area
taskstates: dw 0, 0, 0, 0, 0 ; task0 regs
dw 0, 0, 0, 0, 0 ; task1 regs
dw 0, 0, 0, 0, 0 ; task2 regs
current: db 0 ; index of current task
chars: db '\|/-' ; shapes to form a bar
; one task to be multitasked
taskone: mov al, [chars+bx] ; read the next shape
mov [es:0], al ; write at top left of screen
pf3
pf4
pf5
pf8

Partial preview of the text

Download Multitasking and Debugging-Microprocessor and Assembly Language Programming-Lecture Notes and more Study notes Microprocessor and Assembly Language Programming in PDF only on Docsity!

To experience the power of assembly language we introduce how to

implement multitasking. We observed in the debugger that our thread of

instructions was broken by the debugger; it got the control, used all

registers, displayed an elaborate interface, waited for the key, and then

restored processor state to what was immediately before interruption. Our

program resumed as if nothing happened. The program execution was in the

same logical flow.

If we have two different programs A and B. Program A is broken, its state

saved, and returned to B instead of A. By looking at the instruction set, we

can immediately say that nothing can stop us from doing that. IRET will

return to whatever CS and IP it finds on the stack. Now B is interrupted

somehow, its state saved, and we return back to A. A will have no way of

knowing that it was interrupted as its entire environment has been restored.

It never knew the debugger took control when it was debugged. It sill has no

way of gaining this knowledge. If this work of breaking and restoring

programs is done at high speed the user will feel that all the programs are

running at the same time where actually they are being switched to and forth

at high speed.

In essence multitasking is simple, even though we have to be extremely

careful when implementing it. The environment of a program in the very

simple case is all its registers and stack. We will deal with stack later. Now to

get control from the program without the program knowing about it, we can

use the IRQ 0 highest priority interrupt that is periodically coming to the

processor.

Now we present a very basic example of multitasking. We have two

subroutines written in assembly language. All the techniques discussed here

are applicable to code written in higher level languages as well. However the

code to control this multitasking cannot be easily written in a higher level

language so we write it in assembly language. The two subroutines rotate

bars by changing characters at the two corners of the screen and have

infinite loops. By hooking the timer interrupt and saving and restoring the

registers of the tasks one by one, it appears that both tasks are running

simultaneously.

Example

; elementary multitasking of two threads [org 0x0100] jmp start

; ax,bx,ip,cs,flags storage area taskstates: dw 0, 0, 0, 0, 0 ; task0 regs dw 0, 0, 0, 0, 0 ; task1 regs dw 0, 0, 0, 0, 0 ; task2 regs

current: db 0 ; index of current task chars: db '|/-' ; shapes to form a bar

; one task to be multitasked taskone: mov al, [chars+bx] ; read the next shape mov [es:0], al ; write at top left of screen

inc bx ; increment to next shape and bx, 3 ; taking modulus by 4 jmp taskone ; infinite task

; second task to be multitasked tasktwo: mov al, [chars+bx] ; read the next shape mov [es:158], al ; write at top right of screen inc bx ; increment to next shape and bx, 3 ; taking modulus by 4 jmp tasktwo ; infinite task

; timer interrupt service routine timer: push ax push bx

mov bl, [cs:current] ; read index of current task mov ax, 10 ; space used by one task mul bl ; multiply to get start of task mov bx, ax ; load start of task in bx

pop ax ; read original value of bx mov [cs:taskstates+bx+2], ax ; space for current task pop ax ; read original value of ax mov [cs:taskstates+bx+0], ax ; space for current task pop ax ; read original value of ip mov [cs:taskstates+bx+4], ax ; space for current task pop ax ; read original value of cs mov [cs:taskstates+bx+6], ax ; space for current task pop ax ; read original value of flags mov [cs:taskstates+bx+8], ax ; space for current task

inc byte [cs:current] ; update current task index cmp byte [cs:current], 3 ; is task index out of range jne skipreset ; no, proceed mov byte [cs:current], 0 ; yes, reset to task 0

skipreset: mov bl, [cs:current] ; read index of current task mov ax, 10 ; space used by one task mul bl ; multiply to get start of task mov bx, ax ; load start of task in bx

mov al, 0x out 0x20, al ; send EOI to PIC

push word [cs:taskstates+bx+8] ; flags of new task push word [cs:taskstates+bx+6] ; cs of new task push word [cs:taskstates+bx+4] ; ip of new task mov ax, [cs:taskstates+bx+0] ; ax of new task mov bx, [cs:taskstates+bx+2] ; bx of new task iret ; return to new task

start: mov word [taskstates+10+4], taskone ; initialize ip mov [taskstates+10+6], cs ; initialize cs mov word [taskstates+10+8], 0x0200 ; initialize flags mov word [taskstates+20+4], tasktwo ; initialize ip mov [taskstates+20+6], cs ; initialize cs mov word [taskstates+20+8], 0x0200 ; initialize flags mov word [current], 0 ; set current task index

xor ax, ax mov es, ax ; point es to IVT base cli mov word [es:84], timer mov [es:84+2], cs ; hook timer interrupt mov ax, 0xb mov es, ax ; point es to video base xor bx, bx ; initialize bx for tasks sti

jmp $ ; infinite loop

The space where all registers of a task are stored is called the process

control block or PCB. Actual PCB contains a few more things that are not

mov cl, 5 shl bx, cl ; multiply by 32 for pcb start

mov ax, [bp+8] ; read segment parameter mov [pcb+bx+18], ax ; save in pcb space for cs mov ax, [bp+6] ; read offset parameter mov [pcb+bx+16], ax ; save in pcb space for ip

mov [pcb+bx+22], ds ; set stack to our segment mov si, [nextpcb] ; read this pcb index mov cl, 9 shl si, cl ; multiply by 512 add si, 256*2+stack ; end of stack for this thread mov ax, [bp+4] ; read parameter for subroutine sub si, 2 ; decrement thread stack pointer mov [si], ax ; pushing param on thread stack sub si, 2 ; space for return address mov [pcb+bx+14], si ; save si in pcb space for sp

mov word [pcb+bx+26], 0x0200 ; initialize thread flags mov ax, [pcb+28] ; read next of 0th thread in ax mov [pcb+bx+28], ax ; set as next of new thread mov ax, [nextpcb] ; read new thread index mov [pcb+28], ax ; set as next of 0th thread inc word [nextpcb] ; this pcb is now used

exit: pop si pop cx pop bx pop ax pop bp ret 6

; timer interrupt service routine timer: push ds push bx

push cs pop ds ; initialize ds to data segment

mov bx, [current] ; read index of current in bx shl bx, 1 shl bx, 1 shl bx, 1 shl bx, 1 shl bx, 1 ; multiply by 32 for pcb start mov [pcb+bx+0], ax ; save ax in current pcb mov [pcb+bx+4], cx ; save cx in current pcb mov [pcb+bx+6], dx ; save dx in current pcb mov [pcb+bx+8], si ; save si in current pcb mov [pcb+bx+10], di ; save di in current pcb mov [pcb+bx+12], bp ; save bp in current pcb mov [pcb+bx+24], es ; save es in current pcb

pop ax ; read original bx from stack mov [pcb+bx+2], ax ; save bx in current pcb pop ax ; read original ds from stack mov [pcb+bx+20], ax ; save ds in current pcb pop ax ; read original ip from stack mov [pcb+bx+16], ax ; save ip in current pcb pop ax ; read original cs from stack mov [pcb+bx+18], ax ; save cs in current pcb pop ax ; read original flags from stack mov [pcb+bx+26], ax ; save cs in current pcb mov [pcb+bx+22], ss ; save ss in current pcb mov [pcb+bx+14], sp ; save sp in current pcb

mov bx, [pcb+bx+28] ; read next pcb of this pcb mov [current], bx ; update current to new pcb mov cl, 5 shl bx, cl ; multiply by 32 for pcb start

mov cx, [pcb+bx+4] ; read cx of new process mov dx, [pcb+bx+6] ; read dx of new process mov si, [pcb+bx+8] ; read si of new process mov di, [pcb+bx+10] ; read diof new process

mov bp, [pcb+bx+12] ; read bp of new process mov es, [pcb+bx+24] ; read es of new process mov ss, [pcb+bx+22] ; read ss of new process mov sp, [pcb+bx+14] ; read sp of new process

push word [pcb+bx+26] ; push flags of new process push word [pcb+bx+18] ; push cs of new process push word [pcb+bx+16] ; push ip of new process push word [pcb+bx+20] ; push ds of new process

mov al, 0x out 0x20, al ; send EOI to PIC

mov ax, [pcb+bx+0] ; read ax of new process mov bx, [pcb+bx+2] ; read bx of new process pop ds ; read ds of new process iret ; return to new process

start: xor ax, ax mov es, ax ; point es to IVT base

cli mov word [es:84], timer mov [es:84+2], cs ; hook timer interrupt sti

nextkey: xor ah, ah ; service 0 โ€“ get keystroke int 0x16 ; bios keyboard services

push cs ; use current code segment mov ax, mytask push ax ; use mytask as offset push word [lineno] ; thread parameter call initpcb ; register the thread

inc word [lineno] ; update line number jmp nextkey ; wait for next keypress

When the program is executed the threads display the numbers

independently. However as keys are pressed and new threads are registered,

there is an obvious slowdown in the speed of multitasking. To improve that,

we can change the timer interrupt frequency. The following can be used to

set to an approximately 1ms interval.

mov ax, 1100 out 0x40, al mov al, ah out 0x40, al

This makes the threads look faster. However the only real change is that

the timer interrupt is now coming more frequently.

MULTITASKING KERNEL AS TSR

The above examples had the multitasking code and the multitasked code

in one program. Now we separate the multitasking kernel into a TSR so that

it becomes an operation system extension. We hook a software interrupt for

the purpose of registering a new thread.

Example

; multitasking kernel as a TSR [org 0x0100] jmp start

; PCB layout: ; ax,bx,cx,dx,si,di,bp,sp,ip,cs,ds,ss,es,flags,next,dummy ; 0, 2, 4, 6, 8,10,12,14,16,18,20,22,24, 26 , 28 , 30

pcb: times 32*16 dw 0 ; space for 32 PCBs

Example

; multitasking TSR caller [org 0x0100] jmp start

; parameter block layout: ; cs,ip,ds,es,param ; 0, 2, 4, 6, 8

paramblock: times 5 dw 0 ; space for parameters lineno: dw 0 ; line number for next thread

;;;;; COPY LINES 028-071 FROM EXAMPLE 10.1 (printnum) ;;;;;

; subroutine to be run as a thread ; takes line number as parameter mytask: push bp mov bp, sp sub sp, 2 ; thread local variable push ax push bx

mov ax, [bp+4] ; load line number parameter mov bx, 70 ; use column number 70 mov word [bp-2], 0 ; initialize local variable

printagain: push ax ; line number push bx ; column number push word [bp-2] ; number to be printed call printnum ; print the number inc word [bp-2] ; increment the local variable jmp printagain ; infinitely print

pop bx pop ax mov sp, bp pop bp retf

start: mov ah, 0 ; service 0 โ€“ get keystroke int 0x16 ; bios keyboard services

mov [paramblock+0], cs ; code segment parameter mov word [paramblock+2], mytask ; offset parameter mov [paramblock+4], ds ; data segment parameter mov [paramblock+6], es ; extra segment parameter mov ax, [lineno] mov [paramblock+8], ax ; parameter for thread mov si, paramblock ; address of param block in si int 0x80 ; multitasking kernel interrupt

inc word [lineno] ; update line number jmp start ; wait for next key

We introduce yet another use of the multitasking kernel with this new

example. In this example three different sort of routines are multitasked by

the same kernel instead of repeatedly registering the same routine.

Example

; another multitasking TSR caller [org 0x0100] jmp start

; parameter block layout: ; cs,ip,ds,es,param ; 0, 2, 4, 6, 8

paramblock: times 5 dw 0 ; space for parameters lineno: dw 0 ; line number for next thread chars: db '|/-' ; chracters for rotating bar message: db 'moving hello' ; moving string message2: db ' ' ; to erase previous string

messagelen: dw 12 ; length of above strings

;;;;; COPY LINES 028-071 FROM EXAMPLE 10.1 (printnum) ;;;;; ;;;;; COPY LINES 073-114 FROM EXAMPLE 10.1 (printstr) ;;;;;

; subroutine to run as first thread mytask: push bp mov bp, sp sub sp, 2 ; thread local variable push ax push bx

xor ax, ax ; use line number 0 mov bx, 70 ; use column number 70 mov word [bp-2], 0 ; initialize local variable

printagain: push ax ; line number push bx ; column number push word [bp-2] ; number to be printed call printnum ; print the number inc word [bp-2] ; increment the local variable jmp printagain ; infinitely print

pop bx pop ax mov sp, bp pop bp retf

; subroutine to run as second thread mytask2: push ax push bx push es

mov ax, 0xb mov es, ax ; point es to video base xor bx, bx ; initialize to use first shape

rotateagain: mov al, [chars+bx] ; read current shape mov [es:40], al ; print at specified place inc bx ; update to next shape and bx, 3 ; take modulus with 4 jmp rotateagain ; repeat infinitely

pop es pop bx pop ax retf

; subroutine to run as third thread mytask3: push bp mov bp, sp sub sp, 2 ; thread local variable push ax push bx push cx

mov word [bp-2], 0 ; initialize line number to 0

nextline: push word [bp-2] ; line number mov bx, 50 push bx ; column number 50 mov ax, message push ax ; offset of string push word [messagelen] ; length of string call printstr ; print the string

mov cx, 0x waithere: push cx ; save outer loop counter mov cx, 0xffff loop $ ; repeat ffff times pop cx ; restore outer loop counter loop waithere ; repeat 0x100 times

push word [bp-2] ; line number mov bx, 50 ; column number 50