Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

assembly - How to properly setup SS, BP and SP in x86 Real Mode?

I want to know how to properly do it, because the way I'm doing it isn't working.

When setting the BP register with 7C00h, then setting the SP register with BP, then pushing some ASCII, then getting the data from the memory to print it with INT 10h, it works just fine.

mov ax, 7C00h
mov bp, ax
mov sp, bp

push 'A'

mov ah, 0Eh
mov al, [7BFEh]
int 10h

The actual output is

A

But when I do this:

mov ax, 7C00h
mov ss, ax
mov bp, ax
mov sp, bp

...

It stops working. The interrupt is called, the cursor moves, but nothing is printed. Also setting SS to 0 doesn't work. Please give a hand.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Looking at that 7C00h value, you're probably working on a bootloader.
And you want the stack to reside below the bootloader.

An important choice that you have to make will be how you want to proceed with the segmented addressing scheme that is in effect at start-up.

ORG 7C00h

This indicates that the first byte of the code will be at offset 7C00h. For this to work well, you'll have to initialize the segment registers to 0000h. Remember that the bootloader was loaded by BIOS at linear address 00007C00h which is equivalent to segment:offset pair 0000h:7C00h.
If you're going to change the SP register, then also change the SS segment register. You don't know what it contains at the start of your code and you should (most) always modify these registers in tandem. First assign SS and directly after assign SP. A mov or a pop to SS blocks many kinds of interruptions between this and the following instruction so that you can safely set a consistent (2-register) stackpointer.

mov ss, ax
mov bp, ax     <== This ignored the above safeguard!
mov sp, bp
ORG  7C00h

mov  bp, 7C00h
xor  ax, ax
mov  ds, ax
mov  es, ax
mov  ss, ax      ;   Keep these close together
mov  sp, bp      ; / 

push 'A'         ; This writes 0000h:7BFEh

mov  bx, 0007h   ; DisplayPage and GraphicsColor
mov  al, [7BFEh] ; This requires DS=0
mov  ah, 0Eh     ; BIOS.Teletype
int  10h

As an alternative and because you've setup BP=7C00h, you could read the stacked character via
mov al, [bp-2].

ORG 0000h

This indicates that the first byte of the code will be at offset 0000h. For this to work well, you'll have to initialize some of the segment registers to 07C0h. Remember that the bootloader was loaded by BIOS at linear address 00007C00h which is equivalent to segment:offset pair 07C0h:0000h.

Because the stack must go below the bootloader, the SS segment register will be different from the other segment registers!

ORG  0000h

mov  bp, 7C00h
mov  ax, 07C0h
mov  ds, ax
mov  es, ax
xor  ax, ax
mov  ss, ax      ;   Keep these close together
mov  sp, bp      ; / 

push 'A'         ; This writes 0000h:7BFEh

mov  bx, 0007h   ; DisplayPage and GraphicsColor
mov  al, [bp-2]  ; This uses SS by default
mov  ah, 0Eh     ; BIOS.Teletype
int  10h

ORG 0200h

I've included this one to show that a linear address has many translations to segment:offset.

ORG 0200h indicates that the first byte of the code will be at offset 0200h. For this to work well, you'll have to initialize the segment registers to 07A0h. Remember that the bootloader was loaded by BIOS at linear address 00007C00h which is equivalent to segment:offset pair 07A0h:0200h.

Because the 512-bytes stack goes below the bootloader, the SS segment register will again be equal to the other segment registers!

ORG  0200h

mov  bp, 0200h
mov  ax, 07A0h
mov  ds, ax
mov  es, ax
mov  ss, ax      ;   Keep these close together
mov  sp, bp      ; / 

push 'A'         ; This writes 07A0h:01FEh

mov  bx, 0007h   ; DisplayPage and GraphicsColor
mov  al, [bp-2]  ; This uses SS by default
mov  ah, 0Eh     ; BIOS.Teletype
int  10h

You can also fetch the character with mov al, [01FEh].


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...