directive
gives a clue to the assembler that will affect how the program gets compiled.
Not translated to machine code!
assembler specific- different assemblers might have different directives
instruction
translated to a machine code instruction that the cpu will execute
bios requires last two bytes of first sector are aa55
ORG(directive)
The ORG instruction alters the setting of the location counter and thus controls the structure of the current control section. This redefines portions of a control section.
>>-+--------+--ORG----------------------------------------------> '-symbol-' >--+--------------------------------------------+-------------->< '-expression-+-----------------------------+-' '-,-+-boundary--+---------+-+-' | '-,offset-' | '-,--offset-------------'
- symbol
- Is one of the following:
- An ordinary symbol
- A variable symbol that has been assigned a character string with a value that is valid for an ordinary symbol
- A sequence symbol
If symbol denotes an ordinary symbol, the ordinary symbol is defined with the value that the location counter had before the ORG statement is processed.
- expression
- Is a relocatable expression, the value of which is used to set the location counter. If expression is omitted, the location counter is set to the next available location for the current control section.
- boundary
- Is an absolute expression that must be a number that is a power
of 2 with a range from 2 (halfword) to 4096 (page). If boundary exceeds
the SECTALGN value, message ASMA500W is issued. This
message is not issued if the section being processed is a Reference
Control Section (DSECT, DXD, or COM).
boundary must be a predefined absolute expression whose value is known at the time the ORG statement is processed.
If the boundary operand is greater than 16, the GOFF option must be specified in addition to the SECTALGN option.
- offset
- Any absolute expression
The resultant location counter is calculated as follows:
- Evaluate expression.
- If boundary is specified, round the result to the next multiple of boundary.
- If offset is specified, adjust the result by adding offset.
ORG emits no "fill" bytes for bytes skipped in any direction.
In general, symbols used in expression need not have been previously defined. However, the relocatable component of expression (that is, the unpaired relocatable term) must have been previously defined in the same control section in which the ORG statement appears, or be equated to a previously defined value.
A length attribute reference to the name of an ORG instruction is always invalid. Message ASMS042E is issued, and a default value of 1 is assigned.
An ORG statement cannot be used to specify a location below the beginning of the control section in which it appears. For example, the following statement is not correct if it appears less than 500 bytes from the beginning of the current control section. ORG *-500
This is because the expression specified is negative, and sets the location counter to a value larger than the assembler can process. The location counter wraps around (the location counter is discussed in detail in Location counter).
If you specify multiple location counters with the LOCTR instruction, the ORG instruction can alter only the location counter in use when the instruction appears. Thus, you cannot control the structure of the whole control section using ORG, but only the part that is controlled by the current location counter.
An ORG statement cannot be used to change sections or LOCTR segments. For example: AA CSECT
X DS D
Y DS F
BB CSECT
ORG Y
is invalid, because the section containing the ORG statement (BB) is not the same as the section in AA in which the ORG operand expression Y is defined. With the ORG statement, you can give two instructions the same location counter values. In such a case, the second instruction does not always eliminate the effects of the first instruction. Consider the following example:
ADDR DC A(ADDR)
ORG *-4
B DC C'BETA'
In this example, the value of B ('BETA') is destroyed by the relocation of ADDR during linkage editing.
The following example shows some examples of ORG using the boundary and offset operands:origin csect
ds 235x Define 235 bytes
org origin,,3 Move location counter back to start + 3
org *,8 Align on 8 byte boundary
org *,8,-2 Align to 8 byte boundary -2 bytes
translate dc cl256' ' Define aligned translate table
org translate+c'a'
dc c'ABCDEFGHI'
org translate+c'j'
dc c'JKLMNOPQR'
org translate+c's'
dc c'STUVWXYZ'
org translate+c'A'
dc c'ABCDEFGHI'
org translate+c'J'
dc c'JKLMNOPQR'
org translate+c'S'
dc c'STUVWXYZ'
org ,
end
If a control section has not been previously established, ORG initiates an unnamed (private) control section.
BITS (directive)
tells assembler to emit 16/32/64 bit code
JMP unconditional jump
DB byte1 , byte2,byte3
stands for define bytes. writes bytes to the assembled binary file
times number instruction/data
repeats given instruction or piece of data a number of times
mov dst,src
moves from destination to src
dst=src
in nasm
$
special symbol which is equal to the memory offset of the current line
$$
special symbol which is equal to the memory offset of the begining of the current section ( in this case program)
$-$$ give size of program so far in bytes
DW word1,word2,word3...
stands for define words. writes given words 2 byte vallue encoded on little endian to the assembled binary file
General purpose registers
AL,AH,AX,EAX,RAX R8B,R8W,R8D,R8 R12B,R12W,R12D,R12
BL,BH,BX,EBX,RBX R9B,R9W, R9D,R9 R13B,R13W,R13D,R13
CL,CH,CX,ECX,RCX R10B,R10W,R10D,R10 R14B,R14W,R14D,R14
DL,DH,DX,EDX,RDX R11B,R11W, R11D,R11 R15B,R15W,R15D,R15BPL,BP,EBP,RBP DIL,DI,EDI,RDI
SIL,SI,ESI,RSI SPL,SP,ESP,RSP
Status registers
IP,EIP,RIP FLAGS,EFLAGS,RFLAGS
segment registers
CS,SS,DS,ES,FS,GS
protected mode registers
GDTR,IDTR,TR,LDTR
control registers
CR0,CR3,CR4,CR7,CR10,CR13
CR1,CR3,CR5,CR8,CR11,CR14
CR2,MSW,CR6,CR9,CR12,CR15,MXCSR
debug registers
DR0,DR3,DR6,DR9
DR1,DR4,DR7,DR10,DR12,DR14
DR2,DR5,DR8,DR11,DR13,DR15
Floating point unit registers
ST(0),MM0,ST(1),MM1 SW,FP_IP,FP_DP,FP_CS
ST(2),MM2,ST(3),MM3 SW,FP_DS
ST(4),MM4,ST(5),MM5 TW,FP_OPC,FP_DP,FP_IP
ST(6) ,MM6,ST(7), MM7
SIMD registers
ZMM0-ZMM31
YMM0-YMM15
XMM0-XMM15
8086 CPU had 20 bit address bus
access = 2^29 = 1 mb
the ram at that time were 64-128 kb memory
segment and offset scheme of memory
in this scheme you address memory using two 16 bit value
segment and the offset
0x1234:0x5678
segment:offset
each segment contains 64 kb of memory each byte can be acessed by using offset value
real_address= segment*16 + offset
shifting segment four to the left in hex shift segment left by one
this makes multiple ways to access same memory
segment:offset real address
0x0000:0x7C00 0x7C00
0x0001:0x7BF0
0x0010:0x7B00
0x00C0:0x7000
0x07c0:0x0000
memory segmentation
these registers are used to specify currently active segments :
cs = currently running code segment
the sgement where processor executes from , ip /program counter gives offseet only
ds = data segment
ss = stack segment
es,fs,gs = extra data segments
code segment can only be modified by using jump
referencing a memory location
segment : [ base+ index* scale + displacement]
all fields are optional
segment : CS,DS,ES,FS,GS,SS (DS if unspecified, when base register is bp ss is default)
base : 16 bits bp/bx
index: 16 bits SI/DI
32/64 any general purpose register
scale : 32/64 bits only 1,2,4 or 8
displacement : (signed) constant value
code segment register is set by bios to o or difference offset 7c0, 7c00,
we cant write constant directly to setment register, we use intermediary regsiter
stack is piece of memory that we can access in fifo manner using push and pop
when you call function the return address is added to the stack, when we return from the function processor will read the return address from the stack and then jump to it
stack grows downwards
sp points to the top of stack
when you push something sp is decremented by the number of bytes pushed and then data is written to the memory
thats why we set stack to point to the start of os because it grows downward ,
if we set it up to the end of our program it would overwrite our program
so begining of os is safe point
laodsb,loadsw,loadsd
these instruction load a byte,word,double-word from ds:si into al/ax/eax
then increment si by the number of bytes loaded
or destination, source
perfoms bitwise or between source and destination, stores result in destination
also modifies some flags in flags register such as zero flag if result is zero
interrupts
a signal which make the processor stop what it is doing in order to handle that signal
can be triggered by:
1. an exception ( eg divide by zero , segmentation fault, page fault)
2. hardware ( keyboard key pressed or released, timer tick, disk controller finished an operation)
3. software throught int instruction 0-255 interrupts
int 10h -- video
int 11h -- equipment check
int 12h -- memory size
int 13h -- disk I/O
int 14h -- serial communications
int 15h -- cassette
int 16h -- keyboard I/O
bios int 10h
ah= 00h -- set video mode
ah=01h -- set cursor shape
ah =02h --set cursor position
ah=03h -- get cursor position and shape
...
ah=0eh -- write character in tty mode
bios int 10h,ah=oeh
prints a character to the screen in tty mode
ah=oe
al= ascii character to write
bh=page number (text modes)
bl = foreground pixel color (graphics mode)
returns nothing
- cursor advances after write
-characters bel (7), bs(8), lf(a) and cr(d) are treated as control codes
sudo apt install qemu-system-x86 qemu-system-gui
mkdir os
cd os
mkdir src
cd src
nano main.asm
org 0x7C00
bits 16
main:
hlt
.halt:
jmp .halt
times 510-($-$$) db 0
dw 0AA55h
cd ..
mkdir build
sudo apt install make nasm
nano Makefile
ASM=nasm
SRC_DIR=src
BUILD_DIR=build
$(BUILD_DIR)/main_floppy.img : $(BUILD_DIR)/main.bin
cp $(BUILD_DIR)/main.bin $(BUILD_DIR)/main_floppy.img
truncate -s 1440k $(BUILD_DIR)/main_floppy.img
$(BUILD_DIR)/main.bin: $(SRC_DIR)/main.asm
$(ASM) $(SRC_DIR)/main.asm -f bin -o $(BUILD_DIR)/main.bin
$ make
nasm src/main.asm -f bin -o build/main.bin
cp build/main.bin build/main_floppy.img
truncate -s 1440k build/main_floppy.img
qemu-system-i386 -fda build/main_floppy.img
nano src/main.asm
org 0x7C00
bits 16
%define ENDL 0x0D, 0x0A
start:
jmp main
;
; Prints a string to the screen
; Params:
; - ds:si points to string
;
puts:
; save registers we will modify
push si
push ax
.loop:
lodsb ; loads next character in al
or al, al ; verify if next character is null?
jz .done
mov ah, 0x0E ; call bios interrupt
mov bh, 0 ; set page number to 0
int 0x10
jmp .loop
.done:
pop ax
pop si
ret
main:
; setup data segments
mov ax, 0 ; can't set ds/es directly
mov ds, ax
mov es, ax
; setup stack
mov ss, ax
mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory
; print hello world message
mov si, msg_hello
call puts
hlt
.halt:
jmp .halt
msg_hello: db 'Hello world!', ENDL, 0
times 510-($-$$) db 0
dw 0AA55h
make
qemu-system-i386 -fda build/main_floppy.img
Comments
Post a Comment