flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > mov ax, [sp], error: reserved word used as symbol |
Author |
|
revolution 02 Aug 2019, 18:15
In 16-bit mode only SI, DI, BX and BP can be used to address memory.
You will need to use something like this: Code: mov bp,sp mov ax,[bp] Code: push bp mov bp,sp mov ax,[bp+2] pop bp Code: mov ax,[ss:bx+2] |
|||
02 Aug 2019, 18:15 |
|
fpissarra 03 Aug 2019, 15:01
@revolution is totally right pointing out that only BX, BP, SI and DI can be used as pointers to access memory in 16 bits pre 386 instruction set. The flexible way, where you can use ANY register, was introduced by 80386 and can be used in 16 bits code (unless your processor is pre 386!)...
For example, all instructions below will cause the same error in 16 bits, pre 386, code: Code: mov ax,[dx] ; DX cannot be used this way! mov ax,[bx+dx] ; BX is 'right', but DX isn't! Another thing that isn't available to pre 386 instruction set is scaling: Code: mov ax,[bx+2*si+2] ; 2*si isn't available! Here we use BX and SI, but scaling isn't available! BUT... you can use 386 instruction set in 16 bits mode if you want: Code: mov ax,[ebx+2*esi+2] ; This WORKS! In 16 bits code the upper 16 bits of 32 bits registers are discarded. The logical address is still calculated by ((segment << 4) + offset), there the physical address is 20 bits long and each part (segment and offset) are 16 bits. And, using 32 bits registers you can use ANY registers as you intended: Code: mov ax,[esp] You don't need to zero the upper 16 bits of ESP to use this. The penalty is, when using 32 bits registers as pointers, like this, the compiler will prefix your instruction with 0x67. When using 32 bits registers as source or targets of an instruction the prefix 0x66 is added. See this example: Code: 8B 07 mov ax,[bx] 66 8B 07 mov eax,[bx] 67 8B 03 mov ax,[ebx] 66 67 8B 03 mov eax,[ebx] |
|||
03 Aug 2019, 15:01 |
|
revolution 03 Aug 2019, 15:08
fpissarra wrote: In 16 bits code the upper 16 bits of 32 bits registers are discarded. The logical address is still calculated by ((segment << 4) + offset), there the physical address is 20 bits long and each part (segment and offset) are 16 bits. There is also the matter of the limit value in the hidden shadow segment bits. If the address exceeds the limit then the CPU generates an exception. We can use unreal-mode to set the limit to another value, but that starts to get into more advanced usage of the CPU. |
|||
03 Aug 2019, 15:08 |
|
fpissarra 03 Aug 2019, 15:30
revolution wrote: I can't test this right now, but I think that is not correct. IIRC the full 32-bit address is computed and used. revolution wrote: There is also the matter of the limit value in the hidden shadow segment bits. If the address exceeds the limit then the CPU generates an exception. We can use unreal-mode to set the limit to another value, but that starts to get into more advanced usage of the CPU. "In 16 bits code" as in "in real mode"... There is no "exception" of this kind in real mode. For example, the logical address 0xffff:0xffff will result in a 21 bits physical address (0x10FFEF), but if Gate A20 isn't enabled the memory access will be at address 0x0FFEF (20 bits long). If it is enabled the processor will access the extra segment above 1 MiB limit (That's what HIMEM.SYS in old DOS allows you to do)... In protected mode pos-386 you should use 32 bits registers, but in REAL MODE you can use them without any worries about the attributes in GDT or LDT... Anyway... in real mode, using 32 bits registers to calc the effective address, all 32 bits ARE used, but the memory access will be limited (by hardware and processor mode) to 21 bits, max... |
|||
03 Aug 2019, 15:30 |
|
revolution 03 Aug 2019, 15:37
Real mode can still access the 32-bit instructions and registers with the 0x66 and 0x67 override prefixes. You need to be careful about not exceeding the address range by using addresses too large. For 16-bit instructions using BX (not EBX) then what you say is correct, the BX register cannot exceed 2^16, but EBX can.
Code: use16 mov ebx,0xfff00000 mov ax,[bx] ;okay mov ax,[ebx] ;fault in real mode, address exceeds the limit of 0xffff for DS segment fpissarra wrote: Anyway... in real mode, using 32 bits registers to calc the effective address, all 32 bits ARE used, but the memory access will be limited (by hardware and processor mode) to 21 bits, max... |
|||
03 Aug 2019, 15:37 |
|
antonyprojr 03 Aug 2019, 20:14
I need to correct myself, i said that my OS was in real mode, well, my code is based in the open source MichalOS project https://sourceforge.net/projects/michalos/ (written with Netwide Assembler, but i ported it to Flat Assembler) it's clearly described that the OS works is UNreal mode, not in real mode as i said. When I change the interrupt 1Ch location(to handle the timer interrupt where i want to make the context switch), I'm already in UNreal mode.
Sorry for that! So, rephrasing: How to read IP(Instruction Pointer) in Big UNreal Mode, where memory access is up to 4GB, but the code limited to 64KB, when interrupt 1Ch is triggered? (Inside the interrupt, to where iret command will return when called). |
|||
03 Aug 2019, 20:14 |
|
revolution 03 Aug 2019, 21:07
In real and unreal modes (which are the same thing actually just with a different limit for each segment register) the stack pointer (E)SP is not saved by an interrupt. (E)SP will still be whatever the interrupted task was using less six bytes (or four bytes for software interrupts) for the saved CS, IP, and flags values. So you can use BP (or ESP) to access the saved IP value on the stack.
|
|||
03 Aug 2019, 21:07 |
|
antonyprojr 08 Aug 2019, 02:49
With help of @revolution and debug with Bochs, i can see that the Instruction Pointer can be easily accessed inside the interrupt by:
Code: mov ax, [bp – 8] ;Now IP is in ax Thank you all of yours for the help! |
|||
08 Aug 2019, 02:49 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.