assembly strcmp function acting weirdly

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Re: assembly strcmp function acting weirdly

Post by glauxosdever »

Hi,

Kirdow wrote:
omarrx024 wrote:You loaded your kernel to 0x7E00:0x0000, not 0x7E00. Segmented address 0x7E00:0x0000 corresponds to the linear address 0x7E000. Your segment registers should have 0x7E00 and your whole file should be ORG 0.
Hmm. So what do I have to change? What lines do I need to change and to what?
If you are asking for this either:
  • You have not understood real mode segmentation;
  • You don't know assembly.
If this is the first case, just read about segmentation in real mode. If this is the second case, absolutely learn assembly.

Edit: While reading more carefully I saw that omarrx024 actually wanted Kirdow to load his kernel at 0x7E00. Never overwrite the bootloader while it is executed!


Regards,
glauxosdever
User avatar
Kirdow
Member
Member
Posts: 35
Joined: Sun Sep 06, 2015 2:20 pm
Libera.chat IRC: Kirdow
Location: Sweden

Re: assembly strcmp function acting weirdly

Post by Kirdow »

glauxosdever wrote: If you are asking for this either:
You have not understood real mode segmentation;
You don't know assembly.
Let's start with the second one. I do know 16bit assembly so much that I can use it, but I don't know every aspect. Though moving to 32-bit and 64-bit isn't where I will go yet.
For the first one, not much, just a little. I've searched google tons of times with different keywords about segments, and most say just what CS, DS, ES etc stand for, like Code Segment, Data Segment, Extra Segment. And some of them say that Major systems like OSX, Linux and Windows use Paging. I find like none actually explaining (maybe you got a link?).
glauxosdever wrote: Edit: While reading more carefully I saw that omarrx024 actually wanted Kirdow to load his kernel at 0x7E00. Never overwrite the bootloader while it is executed!
Actually bootloader is loaded to 0x7c00, and the kernel should be loaded at 0x7e00, so we're not actually overwriting the bootloader with the kernel, we're putting the kernel right after the bootloader.
But I have a very hard time understanding "what to do" with just text, it's not about training, it's more from a disorder. So some code to explain would be really helpful.
User avatar
TightCoderEx
Member
Member
Posts: 90
Joined: Sun Jan 13, 2013 6:24 pm
Location: Grande Prairie AB

Re: assembly strcmp function acting weirdly

Post by TightCoderEx »

Your boot loader to read in kernel @ 7E00 can be as simple as this.

Code: Select all

                   BDA  equ  0x0040     ; BDA segment
                   MEM  equ  0x0013     ; Offset to memsize.

                ReBoot  equ  0x0019
       SYSTEM_SERVICES  equ  0x0015

        DISK_IO    equ  0x0013
              D_STATUS     equ  0x0001
                D_READ     equ  0x0200
               D_WRITE     equ  0x0300
                GET_DP     equ  0x0048

        jmp     0x7c0:Begin             ; For quirky BIOS's so we know CS = 7C0H
        
  Begin:

        mov     ax, BDA                 ; Point to BIOS DATA AREA
        mov     ds, ax
        mov     ax, [MEM]               ; Get number of 1k pages. Probably 27FH
        shl     ax, 6                   ; Convert to segment address
        sub     ah, 16

        cli
        mov     ss, ax
        xor     sp, sp
        sti

        mov     ax, cs
        add     ax, 32
        mov     es, ax
        xor     bx, bx                  ; ES:BX = 0x7c0:0

        mov     ax, D_READ + 8          ; AH = 2, AL = 8 sectors to read
        mov     cx, 2                   ; Begin @ sector 2
        mov     dh, 0                   ; Head 0, probably was that already
        int     DISK_IO
        jc      Failed

        jmp     0:0x7e00                ; Jump to second stage.

       times   506 - $  db 90H
                
  Failed:
       int     0x16
       int     ReBoot
               dw      0xAA55
Probably one of the most important things to consider in a boot loader is where the stack is. My preference is to put it at top of conventional memory. ES:BX set to 7e0:0 or 0:7e00 or 2ce:5120 are all equivalent, so low level programming dictates a real good understanding of architecture and instructions set. PC Assembly Language would probably be a good resource for you to get a better understanding of all aspects of assembly development.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: assembly strcmp function acting weirdly

Post by BrightLight »

Kirdow wrote:Hmm. So what do I have to change? What lines do I need to change and to what?
If you want to stay at 0x7E00:0x0000 and not 0x7E00, you'll need this at the beginning of your kernel:

Code: Select all

bits 16			; if using NASM
use16			; maybe you're using FASM?
org 0x0000

os_main:
	cli
	cld
	mov ax, 0x7E00
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, 0
	sti

	; Whatever code you want...
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: assembly strcmp function acting weirdly

Post by Roman »

NASM can understand "use16" too by the way.
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Re: assembly strcmp function acting weirdly

Post by glauxosdever »

Hi,

Kirdow wrote:
glauxosdever wrote: Edit: While reading more carefully I saw that omarrx024 actually wanted Kirdow to load his kernel at 0x7E00. Never overwrite the bootloader while it is executed!
Actually bootloader is loaded to 0x7c00, and the kernel should be loaded at 0x7e00, so we're not actually overwriting the bootloader with the kernel, we're putting the kernel right after the bootloader.
Hands down, you are right with this one. I didn't bother with bootloaders for a long time, so I forgot the actual address (I just assumed it's the one used here).
Kirdow wrote:I've searched google tons of times with different keywords about segments, and most say just what CS, DS, ES etc stand for, like Code Segment, Data Segment, Extra Segment. And some of them say that Major systems like OSX, Linux and Windows use Paging. I find like none actually explaining (maybe you got a link?).
It's on the wiki http://wiki.osdev.org/Segmentation#Real_mode.
omarrx024 wrote:If you want to stay at 0x7E00:0x0000 and not 0x7E00
He doesn't want. EBDA (Extended BIOS data area) ends at 0x9000:0xFFFF and can be as large as 128 KiB, so it can start at 0x8000:0x0000. With segment 0x7E00 you unfortunately can access up to 0x7E00:0xFFFF, which is 0x7E00*0x10+0xFFFF = 0x7E000+0xFFFF = 0x8DFFF > 0x80000.

Ideally you would like to load a second stage loader (I haven't done it yet) which prepares the environment (switches to protected or long mode) and loads the kernel at 0x00100000.


Regards,
glauxosdever
azblue
Member
Member
Posts: 147
Joined: Sat Feb 27, 2010 8:55 pm

Re: assembly strcmp function acting weirdly

Post by azblue »

Kirdow wrote:
glauxosdever wrote: You have not understood real mode segmentation;
... about segments, and most say just what CS, DS, ES etc stand for, like Code Segment, Data Segment, Extra Segment. And some of them say that Major systems like OSX, Linux and Windows use Paging. I find like none actually explaining (maybe you got a link?).
For people that don't have a firm grasp on real mode segmentation I'd recommend setting all your segments to 0; that essentially gives you a 16-bit "flat mode." You're limited to 64KB, but you're not going to move beyond that without really understanding RM segmentation anyway, so this works to get you started.

As for an explanation of how it works, your segment starts at segment << 4. All instructions are executed from the code segment, pushes, pops, reads/writes from (e)sp, (e)bp are, as someone else already said, accessed from SS. Most data uses DS but some uses ES.

Let's say DS = 1, ES =2, SS = 3

Code: Select all

mov ax, [bp] ;reads from linear address 3*16+bp
lodsb ;reads from linear address 1*16+bp
stodsb ;reads from linear address 2*16+bp

User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: assembly strcmp function acting weirdly

Post by BrightLight »

azblue wrote:Let's say DS = 1, ES =2, SS = 3

Code: Select all

mov ax, [bp] ;reads from linear address 3*16+bp
lodsb ;reads from linear address 1*16+bp
stodsb ;reads from linear address 2*16+bp

LODSB/W/D reads from DS:SI, STOSB/W/D writes to ES:DI, not BP.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Kirdow
Member
Member
Posts: 35
Joined: Sun Sep 06, 2015 2:20 pm
Libera.chat IRC: Kirdow
Location: Sweden

Re: assembly strcmp function acting weirdly

Post by Kirdow »

omarrx024 wrote:
Kirdow wrote:Hmm. So what do I have to change? What lines do I need to change and to what?
If you want to stay at 0x7E00:0x0000 and not 0x7E00, you'll need this at the beginning of your kernel:

Code: Select all

bits 16			; if using NASM
use16			; maybe you're using FASM?
org 0x0000

os_main:
	cli
	cld
	mov ax, 0x7E00
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, 0
	sti

	; Whatever code you want...
So. Now this is my boot.asm as you guys gave me it:

Code: Select all

BDA equ 0x0040			; BDA segment
MEM equ 0x0013			; Offset to memsize

ReBoot equ 0x0019
SYSTEM_SERVICES equ 0x0015

DISK_IO equ 0x0013
D_STATUS equ 0x0001
D_READ equ 0x0200
D_WRITE equ 0x0300
GET_DP equ 0x0048

jmp 0x7c0:Begin				; For quirky BIOS's so we know CS = 7c0H
;----------------------------
; standard variables
;----------------------------
	
Begin:
	mov ax, BDA		; Points to BIOS DATA AREA
	mov ds, ax
	mov ax, [MEM]	; Get number of 1k pages. Propably 27Fh
	shl ax, 6		; Convert to segment address
	sub ah, 16
	
	cli
	mov ss, ax
	xor sp, sp
	sti
	
	mov ax, cs
	add ax, 32
	mov es, ax
	xor bx, bx		; ES:BX = 0x7c0:0
	
	mov ax, D_READ + 8	; AH = 2, AL = 8 sectors to read
	mov cx, 2			; Begin @ sector 2
	mov dh, 0			; Head 0, probably was that already
	int DISK_IO
	jc Failed
	
	jmp 0:0x7e00		; Jump to second stage.
	
	times 506 - ($-$$) db 90H
	
Failed:
	int 0x16
	int ReBoot
	dw 0xAA55
and this is my kernel.asm:

Code: Select all

	BITS 16
	ORG 0x0000
; kernel.asm
	
;----------------------------;
; Operating System Functions ;
;----------------------------;
os_main:
	
	cli
	cld
	mov ax, 0x7E00
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, 0
	sti
	
	mov si, msg_string
	call .print_string
	
	jmp $
	
.print_string:
	lodsb
	
	or al, al
	jz .done
	mov ah, 0x0E
	mov bh, 0x00
	mov bl, 0x0F
	int 0x10
	jmp .print_string
.done:
	ret
	
msg_string		db "Hello And Welcome", 0

times 0x1000-($-$$) db 0
and..... "Hello And Welcome" doesn't display. (Note: I temporary removed the code from kernel. I will put it back once this is working again).

I've done what you guys told me. I think. Load the kernel to 0x7e00:0x0000 and set up the segments. and it doesn't show the text.
Why not now?
Octocontrabass
Member
Member
Posts: 6298
Joined: Mon Mar 25, 2013 7:01 pm

Re: assembly strcmp function acting weirdly

Post by Octocontrabass »

Kirdow wrote:

Code: Select all

	jmp 0:0x7e00		; Jump to second stage.

Code: Select all

	ORG 0x0000
These two lines of code disagree.

You are jumping to offset 0x7E00, but you have told the assembler that your code is located at offset 0x0000. You have two choices:
  • jmp 0x07E0:0x0000 and ORG 0x0000
  • jmp 0x0000:0x7E00 and ORG 0x7E00
Pick either of those options and your code will work.
User avatar
Kirdow
Member
Member
Posts: 35
Joined: Sun Sep 06, 2015 2:20 pm
Libera.chat IRC: Kirdow
Location: Sweden

Re: assembly strcmp function acting weirdly

Post by Kirdow »

Octocontrabass wrote: You are jumping to offset 0x7E00, but you have told the assembler that your code is located at offset 0x0000. You have two choices:
  • jmp 0x07E0:0x0000 and ORG 0x0000
  • jmp 0x0000:0x7E00 and ORG 0x7E00
Pick either of those options and your code will work.
So, I changed those, and it still doesn't work.

So I thoght, I tell every step I do, and see if that might lead somewhere.
I have 2 files right now. The boot.asm and kernel.asm.
I assemble both files using "nasm <name>.asm -f bin -o <name>.bin", and copy them over with "partcopy boot.bin 0 200 -f0 0" and "partcopy kernel.bin 0 1000 -f0 200". this makes the bootloader (512 bytes size) first and the kernel (4096 bytes) appear right after, which takes up 8 sectors.
boot.asm looklikes this:

Code: Select all

BDA equ 0x0040			; BDA segment
MEM equ 0x0013			; Offset to memsize

ReBoot equ 0x0019
SYSTEM_SERVICES equ 0x0015

DISK_IO equ 0x0013
D_STATUS equ 0x0001
D_READ equ 0x0200
D_WRITE equ 0x0300
GET_DP equ 0x0048

jmp 0x7c0:Begin				; For quirky BIOS's so we know CS = 7c0H
;----------------------------
; standard variables
;----------------------------
	
Begin:
	mov ax, BDA		; Points to BIOS DATA AREA
	mov ds, ax
	mov ax, [MEM]	; Get number of 1k pages. Propably 27Fh
	shl ax, 6		; Convert to segment address
	sub ah, 16
	
	cli
	mov ss, ax
	xor sp, sp
	sti
	
	mov ax, cs
	add ax, 32
	mov es, ax
	xor bx, bx		; ES:BX = 0x7c0:0
	
	mov ax, D_READ + 8	; AH = 2, AL = 8 sectors to read
	mov cx, 2			; Begin @ sector 2
	mov dh, 0			; Head 0, probably was that already
	int DISK_IO
	jc Failed
	
	jmp 0:0x7e00		; Jump to second stage.
	
	times 506 - ($-$$) db 90H
	
Failed:
	int 0x16
	int ReBoot
	dw 0xAA55
like I said in an earlier message, I want to load the kernel from the floppy disk's second sector and the 7 following sectors and put them in memory at 0x7e00, which is right after the bootloader (0x7c00).
The kernel looklikes this:

Code: Select all

	BITS 16
	ORG 0x7e00
; kernel.asm
	
;----------------------------;
; Operating System Functions ;
;----------------------------;
os_main:
	
	cli
	cld
	mov ax, 0x7E00
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, 0
	sti
	
	mov si, msg_string
	call .print_string
	
	jmp $
	
.print_string:
	lodsb
	
	or al, al
	jz .done
	mov ah, 0x0E
	mov bh, 0x00
	mov bl, 0x0F
	int 0x10
	jmp .print_string
.done:
	ret
	
msg_string		db "Hello And Welcome", 0

times 0x1000-($-$$) db 0 ; note that I do this because I want the kernel to be exactly 4kb size.
I assemble both those using NASM, and then copy them over to the floppy disk using partcopy (see commands used above).
Then I reboot, go into BIOS and start from the floppy (I changed the order so windows (harddrive) starts before floppy to make it easier to develop). What I see is just a black screen with a '_' showing up, not "Hello And Welcome" (I guess the _ is default when nothing is displayed or something?).
Another quick note is that I use VirtualBox (lates version as of when the post is made), which I then run 32-bit Windows XP on. my host is Windows 10 Home.

So, now. why isn't the kernel called and displaying "Hello And Welcome" like it should?
Octocontrabass
Member
Member
Posts: 6298
Joined: Mon Mar 25, 2013 7:01 pm

Re: assembly strcmp function acting weirdly

Post by Octocontrabass »

Kirdow wrote:

Code: Select all

	jmp 0:0x7e00		; Jump to second stage.

Code: Select all

	mov ax, 0x7E00
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
Why are you setting the segment registers to different values instead of using the same value for all of them?
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Re: assembly strcmp function acting weirdly

Post by glauxosdever »

Hi,

glauxosdever wrote:If you are asking for this either:
  • You have not understood real mode segmentation;
  • You don't know assembly.
I was right. :)

Seriously read about segmentation, segment registers, how addresses are formed and learn to use your assembler's specific directives.


Regards,
glauxosdever
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: assembly strcmp function acting weirdly

Post by BrightLight »

Seriously, it looks to me like you loaded it at 0x07E0:0x0000, not 0x7E00:0x0000. Your bootloader loaded the kernel to 0x07E0:0x0000, and you jumped to 0x0000:0x7E00. Therefore your kernel should be ORG 0x7E00 with segments 0x0000.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Kirdow
Member
Member
Posts: 35
Joined: Sun Sep 06, 2015 2:20 pm
Libera.chat IRC: Kirdow
Location: Sweden

Re: assembly strcmp function acting weirdly

Post by Kirdow »

Ok, now I'm very, very confused.

First I had the problem where my strcmp didn't work. appearently it was because of segment registers were set wrong.

So I got this new code first for boot.asm:

Code: Select all

                   BDA  equ  0x0040     ; BDA segment
                   MEM  equ  0x0013     ; Offset to memsize.

                ReBoot  equ  0x0019
       SYSTEM_SERVICES  equ  0x0015

        DISK_IO    equ  0x0013
              D_STATUS     equ  0x0001
                D_READ     equ  0x0200
               D_WRITE     equ  0x0300
                GET_DP     equ  0x0048

        jmp     0x7c0:Begin             ; For quirky BIOS's so we know CS = 7C0H
        
  Begin:

        mov     ax, BDA                 ; Point to BIOS DATA AREA
        mov     ds, ax
        mov     ax, [MEM]               ; Get number of 1k pages. Probably 27FH
        shl     ax, 6                   ; Convert to segment address
        sub     ah, 16

        cli
        mov     ss, ax
        xor     sp, sp
        sti

        mov     ax, cs
        add     ax, 32
        mov     es, ax
        xor     bx, bx                  ; ES:BX = 0x7c0:0

        mov     ax, D_READ + 8          ; AH = 2, AL = 8 sectors to read
        mov     cx, 2                   ; Begin @ sector 2
        mov     dh, 0                   ; Head 0, probably was that already
        int     DISK_IO
        jc      Failed

        jmp     0:0x7e00                ; Jump to second stage.

       times   506 - $  db 90H
                
  Failed:
       int     0x16
       int     ReBoot
               dw      0xAA55
and then I got this for the beginning of the kernel.asm:

Code: Select all

bits 16         ; if using NASM
use16         ; maybe you're using FASM?
org 0x0000

os_main:
   cli
   cld
   mov ax, 0x7E00
   mov ss, ax
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
   mov sp, 0
   sti

   ; Whatever code you want...
The last line says "Whatever code you want..." so I added a print statement:

Code: Select all

bits 16         ; if using NASM
use16         ; maybe you're using FASM?
org 0x0000

os_main:
   cli
   cld
   mov ax, 0x7E00
   mov ss, ax
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
   mov sp, 0
   sti
  ; the following stuff got added.
  mov si, msg_string
   call .print_string
   
   jmp $
   
.print_string:
   lodsb
   
   or al, al
   jz .done
   mov ah, 0x0E
   mov bh, 0x00
   mov bl, 0x0F
   int 0x10
   jmp .print_string
.done:
   ret
   
msg_string      db "Hello And Welcome", 0

times 0x1000-($-$$) db 0
And when I ran this, it didn't work. so I asked what I did wrong. I got this:
Octocontrabass wrote:
Kirdow wrote:

Code: Select all

   jmp 0:0x7e00      ; Jump to second stage.

Code: Select all

   ORG 0x0000
These two lines of code disagree.

You are jumping to offset 0x7E00, but you have told the assembler that your code is located at offset 0x0000. You have two choices:
jmp 0x07E0:0x0000 and ORG 0x0000
jmp 0x0000:0x7E00 and ORG 0x7E00
Pick either of those options and your code will work.
So I changed that to jmp 0x0000:0x7e00 and ORG 0x7e00

Then I got this too:
Octocontrabass wrote:
Kirdow wrote:

Code: Select all

   jmp 0:0x7e00      ; Jump to second stage.

Code: Select all

   mov ax, 0x7E00
   mov ss, ax
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
Why are you setting the segment registers to different values instead of using the same value for all of them?
Well, on that one I say it's because you guys gave me that code. I thought it was valid.

So, what I now wonder is, well, multiple things.
1. Why do I get code and when I then use it you say It's the cause of the problem and ask why I use it?
2. If the code I got was a problem, for example the jmp and org thing, why did I get the wrong in the first place?
3.
omarrx024 wrote: Seriously, it looks to me like you loaded it at 0x07E0:0x0000, not 0x7E00:0x0000. Your bootloader loaded the kernel to 0x07E0:0x0000, and you jumped to 0x0000:0x7E00. Therefore your kernel should be ORG 0x7E00 with segments 0x0000.
Thanks for the info, will try that.
Note: I have a disorder making it harder for me to learn, so when I get the wrong code and you say it should work, and then you say it's wrong, It's making it harder for me in general.
Post Reply