Message board for the users of flat assembler.
> Main > A few general ASM questions...
rhyno_dagreat 12 Oct 2006, 00:19
Hey! I have a few general questions about assembler...
First question: How/what does the ORG statement do?
Second question: How do segment:offsets work and what are they?
An example I have is from my own code:
;BOOTSTART org 7C00h jmp start message db 'Loading RhynOS...',13,10,0 start: xor ax, ax mov ds, ax mov si, message call bios_print load_os: mov ax, 0060h mov es, ax mov bx, 0000h mov ah, 02h mov al, 5 mov ch, 0 mov cl, 2 mov dh, 0 ;mov dl, 0 int 13h jmp 0060h:0000h <================ THIS IS WHAT I'M CURIOUS ABOUT bios_print: lodsb or al, al jz done mov ah, 0x0E int 0x10 jmp bios_print done: call load_os ;BOOTEND times 510-($-$$) db 0 dw 0xAA55
Also, I'm wondering why when you call a segment to jump to (say 60h from the previous code) you see it defined with an extra zero.
And one more thing... what's the difference between linear memory addresses and segment memory addresses (if I'm even specifying this correctly)?
Thank you for your time!
Reason why I'm asking these things is even though I've come a long way, there's still some basic stuff I'm not too certain of... And half the time the code I write doesn't feel like it's my own because I'm constantly needing to get help from others.
|12 Oct 2006, 00:19||
LocoDelAssembly 12 Oct 2006, 01:59
I'll try to answer
First: It establishes the ORiGin, this means that all the code below it will have an origin offset of 7c00h in your case. Since your "JMP start" probably costs two bytes, message is at offset 7c02h. Note that changing the origin to another offset doesn't means that "message" will still referenceable because the boot code is loaded at a base address of 0:7c00h so if you set it wrong then your code will reference "message" wrong (for example setting ORG to 7c01h will reference the message starting from "o" instead of "L". The other parts are not affected by ORG because the JMPs and CALLs of your code all references the labels with IP-relative addresses instead of the absolute address.
Second: In the context of that code (real mode-20 bits addresses) segments just establishes the base address to be added to the offset. This actually happens with protected mode too but in real mode the base address is calculated using the segment number instead of a base address defined in a descriptor referenced by the segment selector (or segment number in the case of real mode).
The way it works is the following:
Given a segment number and an offset, the segment number is multiplied by 16 (or shifted to the left 4 bits) which produces a 20-bit value, to that 20-bit value is then added the offset and with that you get the physical address.
The last question: based on the above look how 0:600 is the same address than 60:0
(0 shl 4) + 600 = 600
(60 shl 4) + 0 = 600 + 0 = 0
Also look that segments overlaps every 16 bytes so 1:0 points to the same physical address than 0:10. To access to physical address 600h you can also use 50:100. Note that in real mode you can have only 16 segments without overlaping each other, so segment:offset pairs in the form of x000:xxxx where x is any hex value will never overlap.
Hope that this helps
 Note that all the addresses here are specified in hex. [/edit]
BTW why do you use
done: call load_os
Note that since you called bios_print instead of JMPing to it, RET will cause the processor to execute the next instruction below the call to bios_print[/edit2]
|12 Oct 2006, 01:59||
rhyno_dagreat 12 Oct 2006, 02:18
Thanks, and as far as the edit, I realized that Thank you though! That helped greatly.
|12 Oct 2006, 02:18||
rhyno_dagreat 12 Oct 2006, 02:20
I realized that too, that is old code though, from when I first started on my first ASM OS back a few months ago, so I was still pretty new.
|12 Oct 2006, 02:20||
< Last Thread | Next Thread >
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.