NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: rfpd on January 08, 2014, 07:27:59 PM
-
mov di, input_buffer
mov al, 0
mov cx, 256
rep stosb
mov ax, input_buffer
mov di, input_buffer
mov ah, 10h
int 16h
stosb
mov ah, 10h
int 16h
stosb
mov ah, 10h
int 16h
stosb
mov ax, 0
stosb
mov si, input_buffer
call Print
input_buffer times 256 db 0
It's not making sense to me why is input_buffer moved to di? and why in the beginning? it should be in the end and from di to the variable, why do we need cx? I didn't understand much, but I think it is a loop counter? Why can't stosb store all of those characters in one string. Why is the variable moved twice to di, why is it moved to ax, why is al set to 0? I searched a lot didn't find a thing except this code that came in a tutorial. About the code, it's for an os, it reads the keyboard input, 3 times, and then prints it all together. Print part is not there because I understand it, but this one confused me a lot. Thanks!
Oh and something else when do what is the real difference between "mov al, [example]" and "mov al, example". Imagine example has a 3 in it, first case will move 3 and the second will move example or will it attach al to example, so everytime al changes, example changes aswell? And why doesn't it work to use lodsb up there, stosb puts the input in di, the I did "mov si, di" and then lodsb. Thanks, again!
-
Knowing instructions such as stosb is not enough. You need to know about the instruction setup when using such instruction.
STOSB instruction setup:
1. AL/AX/EAX as source
2. ES as the segment of the destination
3. DI point to the destination data (so you need ES:DI setup prior to using STOSB)
4. Repetitions in CX/ECX (you guessed correct)
5. Direction flags forward or reverse
You need to know this kind of thing when attempting to use any instruction. RTFM.
Transfer instruction:
1. mov al,byte[example] --> transfers a byte to AL from memory address of [example]
2. mov al, example --> doesn't make sense. It should be mov ax,example. Transfers the address of example to AX.
Start small with simpler examples.
-
Thanks for the answer :D. When an address is moved to ax will it be attached to it? I mean if I change ax will the address change aswell?
-
What do you mean by ES and ES:DI, I googled everywhere but I didn't understand the meaning. Why can't we just fetch from di, is it stored in es? Or es is used to find di? Thanks.
-
No. (if I understand the question) ax will change, but the address of "input_buffer" (or whatever) will not
; move address of input_buffer to di - "stosb" is going to use it
mov di, input_buffer
; clear out buffer - this is probably not necessary
mov al, 0
mov cx, 256
rep stosb
; "stosb" is equivalent to
; mov [es:di], al
; inc di
; with "rep", it does it cx times
mov ax, input_buffer ; useless, as far as I can see
mov di, input_buffer ; since di has changed, we need to reload it
; get one character
mov ah, 10h
int 16h
; put it in our buffer at [es:di], advancing di for the next one
stosb
; again
mov ah, 10h
int 16h
stosb
; and again
mov ah, 10h
int 16h
stosb
; since we have filled the buffer with zeros,
; our string should already be zero-terminated
; I guess this makes sure.
; only al is used, zeroing ax is overkill but does no harm
mov ax, 0
stosb
; presumably "Print" uses this
mov si, input_buffer
call Print
input_buffer times 256 db 0
Next question: "es" is a segment register. In real mode addressing, an address is formed by a segment multiplied by 16, plus the offset (this changes in protected mode!). The usual default segment register is "ds". That is, if we did:
mov al, [di]
it would be equivalent to:
mov al, [ds:di]
We don't need to write the "ds" and usually don't want to. There are exceptions, for example "[bp]" defaults to "[ss:bp]". The reason we're using "es" here is NOT because we're using "[di]" but because we're using the "string instructions" - lodsb, stosb, movsb, scasb, cmpsb, insb, outsb - I may have missed some, and there are "word" and "dword" versions - and I guess "qword" versions, these days. The destination for these (those that have a destination) uses "es" as the segment register.
Presumably, earlier code has set "es" (and "ds" and "ss") where they need to be, and taken care of the other considerations dreamCoder has mentioned. Sometimes people ASSume things they shouldn't. Just because you find something on the internet - even if it claims to be a "tutorial" - doesn't necessarily mean it's right!
Googling for "real mode addressing" might turn up some more useful links. Or ask again here, if you don't understand something.
Best,
Frank
-
Thanks for the answer :D. When an address is moved to ax will it be attached to it? I mean if I change ax will the address change aswell?
Just like Frank said. The answer is no. If you change AX, you destroy the current value of AX for good. The address of example is still intact. What you did in your code seemed to demonstrate this.
mov ax, input_buffer ; address of input_buffer in AX
...
mov ah,10h ;now you destroy it
Take it slowly. Don't rush.
-
What do you mean by ES and ES:DI, I googled everywhere but I didn't understand the meaning. Why can't we just fetch from di, is it stored in es? Or es is used to find di? Thanks.
ES is the segment register, holding the address of a segment (a segment is a memory block, just like a building). Your data (your room in that building) may reside in that segment somewhere and in the case of STOSB setup, the destination data must reside in that segment (where the address of that segment is currently in ES register). The address of the destination data inside the segment must be pointed to by the DI register. So now you have the complete ES:DI address for your input_buffer, as expected by STOSB instruction.
Your confusion revolves around the difference between extra segment and the Extra Segment (ES) register. Don't get them mixed up.
-
mov di, input_buffer
or
mov si, input_buffer
So this is like saying, si and di ask for an address, we give them and then they use that address to store, load data? Like a configuration?
The es:di is like we have an hotel (es) and there we have a person called di, that we must find. So we need to say es:di, like di in es hotel, right? If we only type di it will have no place to look? Is that right?
input_buffer times 256 db 0
Does this means that we can only store one time in a variable? By that logic we do times 256 to store in that variable 256 characters, right?
Thanks for the help, sorry for asking so many questions but I don't understand what I read in the internet.
-
All your assumptions and analogies are quite correct in the case of 16-bit real mode segmentation. Almost every data / instructions in 16-bit real mode has their address in segment:offset format, like CS:IP, DS:DX, ES:DI,SS:BP, DS:yourdata etc etc. DS is the default segment for all data, thus many programmers skip it when addressing their data in memory. So you may not always see them in their full segment:offset format. When an instruction or you change the segment for data to other than the default (DS), you are said to be using segment override. So STOSB is one example of segment override (using ES instead of the default DS for keeping data).
Instructions have unique setup in regards to memory and registers, including STOSB that requires the destination (the place where you'll actually STORE BYTE of your string) to be addressed by ES:DI. So in short, ES (memory) is the building, then the DI will point to the starting address of the particular data (input_buffer) in that segment pointed to by ES (register). Remember, a memory block (segment) becomes an extra segment only when its address is kept in the ES register. Similarly, a random block of memory would only become a data segment only if you place its address into the DS register.
Another example is the famous int 21h, function ah=9 to print a string. This is a good example of segment:offset notation. This interrupt also has its own instruction/interrupt setup.
Instruction Setup for INT 21h to print a null-terminated string:
1. AH = 9h
2. The string offset/address must reside in DX
3. The Segment must be in DS
4. The string must be null-terminated ('$')
The decision on the segment location is application-dependent. In your code, try to find how the author/tutorial setup the ES.
So the keywords here are : segment:offset, instruction setup.
-
Thanks, but now I have a new problem my boot file reached maximum space. What should I do?
Bits 16
jmp Main
Print:
lodsb
cmp al,0
je Done
mov ah, 0eh
int 10h
jmp Print
ret
Done:
ret
Input:
call cposition
mov di, input_buffer
mov cx, 256
rep stosb
mov di, input_buffer
call Prompt
ret
Prompt:
mov ah, 10h
int 16h
stosb
mov ah, 0eh
int 10h
cmp al, 13
je Compare
jmp Prompt
ret
Compare:
mov si, input_buffer
lodsb
mov ah, [help]
cmp al, ah
je helpb
jmp notrec
ret
cposition:
mov ah, 03h
int 10h
mov ah, dh
inc ah
mov dh, ah
mov ah, 02h
mov dl, 0
int 10h
ret
notrec:
call cposition
mov si,notrecz
call Print
jmp Input
ret
helpb:
call cposition
mov si, helpa
call Print
jmp Input
ret
Main:
cli
mov ax, 0x0000
mov ss, ax
mov sp, 0xFFFF
sti
mov ax, 07C0h
mov ds, ax
mov es, ax
mov [bootdrive], dl
mov si,msg
call Print
mov ah, 02h
mov dh, 1
mov dl, 0
int 10h
jmp Input
cli
hlt
bootdrive db 0
helpa db "You called for help, no help to give",0
msg db "Rui OS type help for aditional information", 0
help db "help",0
notrecz db "Command not recognized",0
input_buffer times 256 db 0
times 510 - ($-$$) db 0
dw 0xAA55
-
Thanks, but now I have a new problem my boot file reached maximum space. What should I do?
Hi!
Next code file you have to load from disk.
EDIT0:
You might be interested into bios interrupt 13h - Low Level Disk Services.
Find more information about on BIOS interrupt call (http://en.wikipedia.org/wiki/BIOS_interrupt_call) wikipedia.
-
Yes I already saw it, but I didn't find a site that explained it properly. Thanks I will check this out!
-
Yes I already saw it, but I didn't find a site that explained it properly. Thanks I will check this out!
Here is my source code of bootloader,
that loads next code from floppy drive i think,
and then executes that loaded code.
Here i read that code (load into fixed address 0X007E:0X0000):
.........................
; Read segment
MOV AX,0X007E
MOV ES,AX
MOV BX,0X0000
MOV AH,0X02
MOV AL,1
MOV CH,0
MOV CL,2
MOV DH,0
MOV DL,BYTE [cdDrive]
INT 0X13
JC .ABORT
.........................
Here, later, i jump on it (0X007E:0X0000):
.........................
CLI
JMP 0X007E:0X0000
Notes:
- If still interested, then see attachment, "bootloader.asm".
- Bootloader worked when i tested it, some time ago.
- Next sector must be written to floppy drive first sector, i think.
You should know this site: OsDev.Org (http://wiki.osdev.org/Main_Page), site, is about os development.
Some links from that site, that i liked:
- Babystep (http://wiki.osdev.org/Category:Babystep)
- Beginner Mistakes (http://wiki.osdev.org/Beginner_Mistakes)
Here is one more site named: MikeOs (http://mikeos.berlios.de)
Some links from that site, that i liked:
How to write a simple operating system (http://mikeos.berlios.de/write-your-own-os.html)
There is a section: "Going further", so, that is what you are doing now.
-
Thanks, but now I have a new problem my boot file reached maximum space. What should I do?
Bits 16
jmp Main
Print:
lodsb
cmp al,0
je Done
mov ah, 0eh
int 10h
jmp Print
ret
Done:
ret
Input:
call cposition
mov di, input_buffer
mov cx, 256
rep stosb
mov di, input_buffer
call Prompt
ret
Prompt:
mov ah, 10h
int 16h
stosb
mov ah, 0eh
int 10h
cmp al, 13
je Compare
jmp Prompt
ret
Compare:
mov si, input_buffer
lodsb
mov ah, [help]
cmp al, ah
je helpb
jmp notrec
ret
cposition:
mov ah, 03h
int 10h
mov ah, dh
inc ah
mov dh, ah
mov ah, 02h
mov dl, 0
int 10h
ret
notrec:
call cposition
mov si,notrecz
call Print
jmp Input
ret
helpb:
call cposition
mov si, helpa
call Print
jmp Input
ret
Main:
cli
mov ax, 0x0000
mov ss, ax
mov sp, 0xFFFF
sti
mov ax, 07C0h
mov ds, ax
mov es, ax
mov [bootdrive], dl
mov si,msg
call Print
mov ah, 02h
mov dh, 1
mov dl, 0
int 10h
jmp Input
cli
hlt
bootdrive db 0
helpa db "You called for help, no help to give",0
msg db "Rui OS type help for aditional information", 0
help db "help",0
notrecz db "Command not recognized",0
input_buffer times 256 db 0
times 510 - ($-$$) db 0
dw 0xAA55
Jeez, u have no idea how to setup ES but you are writing a bootloader already? God help us all.