Author Topic: Far JMP in real mode  (Read 7367 times)

Offline Hmail

  • Jr. Member
  • *
  • Posts: 2
Far JMP in real mode
« on: December 17, 2017, 08:36:21 PM »
Hi all,

I am getting into programming in real mode (My 2nd edition from Assembly language Step-by-Step is on it's way ;) ), and I'm following a tutorial that is written in GAS (intel syntax). To get extra experience, I wanted to 'convert' that code to NASM, to really get a grasp of what is going on.
In this tutorial, the following syntax is used:
Code: [Select]
LOAD_SEGMENT = 0x1000

# and then later

    # Make es and ds point to segment where 2nd stage was loaded.
    mov     ax, word ptr LOAD_SEGMENT
    mov     es, ax
    mov     ds, ax
    # Jump to second stage start of code:   
    jmp     LOAD_SEGMENT:0


The JMP instruction is where I'm getting lost. The disassembler shows this as to JMPF 0x1000:0, but when I try to use the LOAD_SEGMENT variable in NASM code, this is the only way I can get the JMP to the proper address:
Code: [Select]
LOAD_SEGMENT: dw 01000h

; and then later...

mov ax,0h ; load offset in ds
mov ds,ax
mov ax,[LOAD_SEGMENT] ; load 1000h in es (segment)
mov es,ax

; Jump to second stage start of code:
push word [LOAD_SEGMENT]
push word 0h
retf

This is code I found  on this forum, from https://forum.nasm.us/index.php?topic=2024.msg8969#msg8969
Now, I'm getting a bit lost here. It looks like I'm saving LOAD_SEGMENT and 0h first in ES and DS, and then again on the stack. However, the jump doesn't work when I leave the first bit out. Is there someone who can explain me what is going on in this code? The GAS code looks a lot easier. Is there a similar way to reproduce this in NASM?


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Far JMP in real mode
« Reply #1 on: December 18, 2017, 12:44:50 AM »
Well... in your first example, LOAD_SEGMENT is a constant (the Nasm syntax is "equ", not "="). In your second example, LOAD_SEGMENT is a variable. The main difference is that a variable needs a segment (ds) as part of the address, a constant does not.
Code: [Select]
LOAD_SEGMENT equ 0x1000
...
jmp LOAD_SEGMENT:0
"ought" to work.

A bootsector is not the easiest place to start (even though the CPU does) and trying to convert from Gas only makes it worse.

If I were you, I'd wait for the book to come in and follow Duntemann first, then get back to the bootsector if you want to. We can discuss this code more if you insist...

Best,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Far JMP in real mode
« Reply #2 on: December 18, 2017, 07:27:44 AM »
Hmmm... Second Edition, you say? I have not read any of Jeff Duntemann's books. I have looked at the code which is available on line. In my humble opinion, there are a couple of errors - translating from the Masm syntax of the first edition to the Nasm syntax of the second edition. This may not apply to the code in the book, but take a look at it and see if it improves the formatting, etc.

Code: [Select]
Only in .: beg2dif.txt
diff -u orig/eat3.asm ./eat3.asm
--- orig/eat3.asm Sun Dec 12 14:18:02 1999
+++ ./eat3.asm Mon Jan 28 19:41:28 2002
@@ -110,7 +110,7 @@
 
 ClrScr:
     mov CX,0          ; Upper left corner of full screen
-    mov DX,LRXY       ; Load lower-right XY coordinates into DX
+    mov DX,[LRXY]       ; Load lower-right XY coordinates into DX
 ClrWin:
     mov AL,0          ; 0 specifies clear entire region
 ScrlWin:
diff -u orig/eat5.asm ./eat5.asm
--- orig/eat5.asm Sun Dec 12 14:25:04 1999
+++ ./eat5.asm Mon Jan 28 21:09:18 2002
@@ -15,7 +15,7 @@
 
 [SECTION .text]             ; Section containing code
 
-%include "BOOK\MYLIB.MAC"        ; Load in screen control macro library
+%include "MYLIB.MAC"        ; Load in screen control macro library
 
 START:                      ; This is where program execution begins:
 
diff -u orig/info.asm ./info.asm
--- orig/info.asm Sun Dec 12 14:29:22 1999
+++ ./info.asm Mon Jan 28 20:44:00 2002
@@ -21,7 +21,7 @@
 START:                      ; This is where program execution begins:
            call VidCheck    ; Initialize all video information variables
 
-           Clear VidSegment,ClearAtom,VidBufSize  ; Clear the screen
+           Clear VidOrigin,ClearAtom,VidBufSize  ; Clear the screen
 
            ; Here we display the name of the program and its author:
            Writeln IDString,LIDString      ; Display the program name
@@ -274,8 +274,8 @@
 ; system and are initialized by the VidCheck procedure:
 ;---------------------------------------------------------------
 DispType   DB      0       ; Code for display adapter type
-VidSegment DW      0B000H  ; Segment of installed display buffer
 VidOrigin  DW      0       ; Offset for FAR pointer to refresh buffer
+VidSegment DW      0B000H  ; Segment of installed display buffer
 VisibleX   DB      80      ; Number of columns on screen
 VisibleY   DB      25      ; Number of lines on screen
 VidBufSize DW      4000    ; Default to 25 X 80 X 2 (char & attribute)
diff -u orig/mylib.mac ./mylib.mac
--- orig/mylib.mac Mon Sep 20 12:04:08 1999
+++ ./mylib.mac Mon Jan 28 20:58:40 2002
@@ -32,8 +32,8 @@
 ;---------------------------------------------------------------
 %macro  Clear 3  ;VidAddress,ClearAtom,BufLength
         les DI,[%1]      ; Load ES and DI from FAR pointer
-        mov AX,%2        ; Load AX with word to blast into memory
-        mov CX,%3        ; Load CX with length of buffer in bytes
+        mov AX,[%2]        ; Load AX with word to blast into memory
+        mov CX,[%3]      ; Load CX with length of buffer in bytes
         shr CX,1         ; Divide size of buffer by 2 for word count
         cld              ; Set direction flag so we blast up-memory
         rep stosw        ; Blast away!
Only in .: orig

As you see, even the professionals can have trouble with syntax translations. Not that you can't translate your Gas example to Nasm, but you'll confuse yourself less if you just use Gas for it...

Best,
Frank


Offline Hmail

  • Jr. Member
  • *
  • Posts: 2
Re: Far JMP in real mode
« Reply #3 on: December 18, 2017, 11:50:22 AM »
Well, changing LOAD_SEGMENT to const was the missing piece of the puzzle, thanks a lot! I agree that it is pretty hard to start with a bootsector, but I'm used to setting unreasonable high goals and then learning as much as possible in my attempts to reach them ;) So far, I learned a *lot* and armed with the bochs debugger, I get a pretty clear sense of what is going on.

I have already read the 3rd edition, and I only found some minor errors, at least the listings in the book that I typed over worked perfectly. I want to read the 2nd edition because that goes deeper into real mode addressing, which the 3rd only briefly touches on. As long as I have a good debugger and some free time, I don't mind working through these kinds of errors. But thanks for the heads up!