Author Topic: Question Problem with "global"  (Read 5677 times)

Offline Guenni60

  • New Member
  • Posts: 1
Question Problem with "global"
« on: March 16, 2016, 03:53:47 PM »
Hello Man and Supporter for NASM.

I had download the Package  nasm-2.11.08-dos
(and some more Packages for other OS's) 
and want to write little Bit Code für 16-Bit-DOS (pur DOS)
as Object-File, which should include in Turbo-Pascal 7 rsp.
Borland-Pascal 7 (patched for RTE 200 because of the notorius
Bug which doesn't run the Progs on Machines faster than  200 MHz).

Now this is the Code:
  ; int_fpu.asn
  ; Ausprobier-Programm für die FPU / 80x87
  ; NASM-Assembler-Programm
  ; Hinweis:
  ; Starte Assemblierung mit 
  ;   NASM  -f bin int_fpu.asn           ; für-DOS Real-Mode
  ;                                      ; Damit erhält man  ein File (leider in Kleinschrift)
  ;   NASM  -f bin int_fpu.asn  -l int_fpu.lst  ; für DOS-Real-Mode
  ;                                             ; Mit dem Parameter -l  erhält man ein Listing-File
  ;                                             ; das neben den Zeilen-Nummer auch den Binär.Code enthält!
  ; Kein "-o int_fpu.obj" angeben!
  ; Sonst erhält man Fehler 47:  .OBJ-Dateiformat  nicht gültig!
  ; Hinweise:
  ; Kann man mit NASM Object-Code erzeugen,
  ; der dann von TP7/BP7 eingebunden werden kann ?
  ; Prinzipiell ja!
  ; Dafür dient die Funktion  int2real 
  ; Probleme gibt es noch in Details (siehe oben).
  ; Ansonsten gibt es im PASCAL-Code den  Fehler "Unbekannter Bezeichner"
  ;    beim Aufruf einer Funktion  Int2Real !   
  ; Grund: Dieser Bezeichner ist nicht im Object-Code enthalten!
  ; Nachdem diese Hürde umschifft war, nun  das Problem mit dem  "-o bin"-Format.
  ; Dieser erlaubt eigentlich kein Exportieren von Extern-  u. Global-Bezeichnern ... 
  ; Historie:
  ; ... (deleted)
  ; 2016.03.01-02  GEWE-PROJEKTE  GLW  Funktion  Int2Real geändert/erstellt,
  ;                               Fehler: Ungültige PUBLIC-Definition in (diesem) OBJ-File
  ; Original-Code für/in/mit NASM:
   ;BITS 32                          ; 32-Bit-Modell ( - kein 16-Bit-Model ???
                                     ; Falsch als 'BITS32' angegeben (Siehe Kapitel 6.1)
    BITS 16                          ; 16-Bit-Modell  - siehe Kapitel 6.1   
  ; %define PASCAL                   ; Vielleicht nur erforderlich für das Makro-Packet c16.mac ?
                                              ; I think we don't need this Declaration
    SECTION .data                    ; Initialisierte Daten
    ;   int32:   dd 1919641698       ; Double-Word  (4 Bytes)   1.919.641.698  1,9 Milliarden 
      ; int64:   dq 1919641698       ; Quarter-Word (8 Bytes)   1.919.641.698  1,9 Milliarden
                                     ; Problem bei/mit NASM:
                                     ; Integer supplied to a DQ-Instruction ...  Daher:
    ;   int64:   dq 1.919641e10      ; Quarter-Word (8 Bytes)   1.919.641*10^10 => 19 Milliarden !
  ; SECTION .bss                     ; Nicht-initialisierte Daten 
    ;   extern   int32               ; Versuch einer EXTERN-Deklaration von int32  Nicht "extern  int32:dd" !
      ; dbl:     resq 1              ; Ergebnis-Feld  'dbl' vom Type  resq  (Quadword) = 8 Bytes
                                     ; Declare an uninitialized storage space: An Array of 1 Real Number
    ;   extern   erg8                ; Versuch einer EXTERN-Deklaration, umbenannt von 'dbl'
   ;SECTION code                     ; 'SECTION' ist gleichbedeutend mit 'SEGMENT'
                                     ; '.text' ist gleichbedeutend mit '.code'
    SEGMENT code private align=16    ; 'private' u. 'align=16' eventuell wichtig für DOS ?  Siehe PDF Kapitel 7.4.1
    ; Neue von GLW erstellte Funktion: 
    global  Int2Real                 ; Funktion im PASCAL-Stil 
   ;global  Int2Real:function        ; Funktion im PASCAL-Stil  Fehler: Object-Format supports no special features for this symbol!
    Int2Real:                        ; function  Int2Real(a : integer; b : integer) : real;
                                     ;   Parameter:  a = Vorkomma-Teil, b = Nachkomma-Stellen
        push    bp 
        mov     bp, sp 
        sub     sp, 0x40             ; 64 Bytes of lokalen Stack-Space
        mov     ax, [bp+8]           ; Erster Parameter der Funktion (Vorkomma-Teil)
        mov     bx, [bp+6]           ; Zweiter Parameter der Funktion (Nachkomma-Stellen)
        fninit                       ; Initialisiere FPU  ohne Vorab-Prüfung
        push    bx                   ; Nachkomma-Teil in BX auf Stack schieben ...
      ; fild    word sp              ; ... und weiter vom Stack auf ST(0) der FPU
      ; mov     cx, 1000             ; Bringe Divisor 1000 in CX
        fidiv   word [bp+8]          ; ... dividiere mit 1000 und bringe Ergebnis als Realzahl nach TOS
        push    ax                   ; Vorkomma-Teil von AX auf Stack schieben ...
        fild    word [bp+8]          ; ... und weiter vom Stack auf ST(0) der FPU
        fadd    st1                  ; Addiere ST(0) + ST(1) => ST(0)
        add     sp, 2                ; Stack um 2 Bytes wieder bereinigen (Ersatz für POP BX)
        add     sp, 2                ; Stack um 2 Bytes wieder bereinigen (Ersatz für POP AX)
    ; Gebe Ergebnis zurück in DX:BX:AX :  / Get Result in DX:BX:AX
      ; Veralteter Code   
      ; fstp    qword [erg8]         ; Speichere TOS (als Real-Zahl) in Ergebnis-Feld 'erg8' mit POP
      ; fninit                       ; Initialisiere FPU, aber ohne Vorab-Prüfung
      ; fstp    qword [ ]            ; Speichere an der durch     Error: Expression Syntax Error 
    ; Mal testweise:   / Only for Testing
    ; Voriger Ablauf unwichtig, schreibe Werte in AX:BX:DX:
    ; Gebe immer  1000,12345  aus!  ; (* Gibt in TEST111.PAS func_a() immer  3.1308...E0005 aus ...
      ; mov     cx, a
        mov     dx, 008Ah
        mov     bx,    0h
        mov     ax, 7A00h
        mov     sp,bp                ; undo "sub sp,0x40" above
        pop     bp
        retf    4      ; ret         ; Zurück zum Aufruf mit der Parameter-Größe von 4 Bytes
      end                            ; of ASM-Code
  ; ende nasm-Code 
; ende int_fpu.asn

Sorry, all Comments are in German - not in English.
But I think you can understand the Code also.
In weighty case you can make answer that I could translate them in Englisch.

I want to get back from the function any Results of Type real
(and other floating-point-Types like  Single, Double, Extended, Comp).
which is not described in any Places.
Which should be get back the Function-Result in DX:BX:AX

I do assemble the Code with
  nasm  -f obj  int_fpu.asn 
  (*.asn is my Variant for Assembler-Programs and Code
  instead of *.asm with TP/INTEL/MASM-Syntax) 
I also try with   -f bin  and/or together with  -o int_fpu.obj 
and sometimes I had try it with  -t

Then I include in TP7 with

    a : real;
  {$L int_fpu.obj}
  function  Int2Real(a : integer; b : integer) : real;  external;
  a := Int2Real(1000,12345);
  writeln(' a = ', a);
 end. (* of program *)

But if I want to compile this Code in TP7
i always get the Error "Error 51: Invalid PUBLIC-Definition"
(after a Lot of other Errors/Problems wich I could have solved).

What does I doing wrong ?

I doesn't find any Hints/Tipps of this Problem in your Description.

Which is the correct Object-Format which should I used ?
If I try '- o bin' I can't use the 'EXTERN' or 'GLOBAL' statement.

I work in the NTVDM of WINDOWS 2000,
but I doesn't assume that this has any Influence it.

Could you get me some Help ?

And a Question more:  Where is the Macro-File  c16.mac  ?
Is this included in the nasm-Program ?
And which Makros are placed in it ?  Where can i find it?
And is the Statement  %define pascal  necessary for me ?

Any Help are I am pleasure and welcome.

Thank you beforehand


Günther Wenzl,

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Question Problem with "global"
« Reply #1 on: March 16, 2016, 07:24:36 PM »
Hi Günther,

Welcome to the Forum!

I speak no german. I "took" German in college but it was Tuesday-Thursday-Saturday at 8:00 in the cow-milking morning. I speak no German.

But code is code!

First, "c16.mac" is in the "misc" directory of the Nasm source code. I don't think it's what you want, but it's short...
Code: [Select]
; NASM macro set to make interfacing to 16-bit programs easier -*- nasm -*-

%imacro proc 1 ; begin a procedure definition

%push proc

  global %1

%1:   push bp

  mov bp,sp

%ifdef FARCODE PASCAL ; arguments may start at bp+4 or bp+6

%assign %$arg 6

%define %$firstarg 6


%assign %$arg 4

%define %$firstarg 4


%define %$procname %1


%imacro arg 0-1 2 ; used with the argument name as a label

%00   equ %$arg

; we could possibly be adding some

; debug information at this point...?

%assign %$arg %1+%$arg


%imacro endproc 0

%ifnctx proc

%error Mismatched `endproc'/`proc'


          mov sp,bp

          pop bp

%ifdef PASCAL

          retf %$arg - %$firstarg

%elifdef FARCODE





__end_%$procname: ; useful for calculating function size



It would work, but I think you're better off without it.

"-f obj" is the output format you want. "-f bin" will give you a flat binary file. You can change the name with the "-o" switch, but it's still a flat binary file. "-f obj" is "OMF" - Object Module Format - which is what Pascal uses, I think.

I get a little confused about here:
Code: [Select]
      ; fild    word sp              ; ... und weiter vom Stack auf ST(0) der FPU
      ; mov     cx, 1000             ; Bringe Divisor 1000 in CX
        fidiv   word [bp+8]          ; ... dividiere mit 1000 und bringe Ergebnis als Realzahl nach TOS
        push    ax                   ; Vorkomma-Teil von AX auf Stack schieben ...
        fild    word [bp+8]          ; ... und weiter vom Stack auf ST(0) der FPU
        fadd    st1                  ; Addiere ST(0) + ST(1) => ST(0)

Commented out, but "sp", even "[sp]" isn't going to work in 16-bit code. You'll have to reference the stack from [bp]... which you do, but you seem to use "fidiv" without having loaded anything, then "fild" and "fadd". Which do you want to do?

I think that if you tell Pascal that the function returns "real", it will expect the result in st0. You want the result in DX:BX:AX? That may be a problem, I'm not sure. Doesn't Pascal expect callee to preserve BX? Might DX:CX:AX be better? In any case, I count 48 bits there. "double" wants 64 bits, and "extended" wants 80 bits. Is that going to be a problem?

You say:
Code: [Select]
  SEGMENT code private align=16
Do you want "private"? It may help to add "class=CODE" (I think that wants to be uppercase?)
Code: [Select]
segment code public align=16 class=CODE
"public" is default, so we shouldn't need to say it... I think "private" may be a mistake.

We probably haven't solved your problem yet, but perhaps I've made it more clear what I'm confused about and we can discuss it more. Sorry about my lack of German.