*** empty log message ***
This commit is contained in:
parent
22e5dda13d
commit
6b2ea2eb8d
1 changed files with 828 additions and 628 deletions
328
doc/nasmdoc.src
328
doc/nasmdoc.src
|
@ -1529,11 +1529,18 @@ label, which means that it is associated with the previous non-local
|
|||
label. So, for example:
|
||||
|
||||
\c label1 ; some code
|
||||
\c .loop ; some more code
|
||||
\c
|
||||
\c .loop
|
||||
\c ; some more code
|
||||
\c
|
||||
\c jne .loop
|
||||
\c ret
|
||||
\c
|
||||
\c label2 ; some code
|
||||
\c .loop ; some more code
|
||||
\c
|
||||
\c .loop
|
||||
\c ; some more code
|
||||
\c
|
||||
\c jne .loop
|
||||
\c ret
|
||||
|
||||
|
@ -1553,6 +1560,7 @@ to, you could write
|
|||
|
||||
\c label3 ; some more code
|
||||
\c ; and some more
|
||||
\c
|
||||
\c jmp label1.loop
|
||||
|
||||
Sometimes it is useful - in a macro, for instance - to be able to
|
||||
|
@ -1571,6 +1579,7 @@ to the local label mechanism. So you could code
|
|||
\c ..@foo: ; this is a special symbol
|
||||
\c label2: ; another non-local label
|
||||
\c .local: ; this is really label2.local
|
||||
\c
|
||||
\c jmp ..@foo ; this will jump three lines up
|
||||
|
||||
NASM has the capacity to define other special symbols beginning with
|
||||
|
@ -1604,6 +1613,7 @@ things like
|
|||
|
||||
\c %define ctrl 0x1F &
|
||||
\c %define param(a,b) ((a)+(a)*(b))
|
||||
\c
|
||||
\c mov byte [param(2,ebx)], ctrl 'D'
|
||||
|
||||
which will expand to
|
||||
|
@ -1616,6 +1626,7 @@ not at definition time. Thus the code
|
|||
|
||||
\c %define a(x) 1+b(x)
|
||||
\c %define b(x) 2*x
|
||||
\c
|
||||
\c mov ax,a(8)
|
||||
|
||||
will evaluate in the expected way to \c{mov ax,1+2*8}, even though
|
||||
|
@ -1636,6 +1647,7 @@ preprocessor will only expand the first occurrence of the macro.
|
|||
Hence, if you code
|
||||
|
||||
\c %define a(x) 1+a(x)
|
||||
\c
|
||||
\c mov ax,a(3)
|
||||
|
||||
the macro \c{a(3)} will expand once, becoming \c{1+a(3)}, and will
|
||||
|
@ -1721,6 +1733,7 @@ example, the following sequence:
|
|||
|
||||
\c %define foo bar
|
||||
\c %undef foo
|
||||
\c
|
||||
\c mov eax, foo
|
||||
|
||||
will expand to the instruction \c{mov eax, foo}, since after
|
||||
|
@ -1813,9 +1826,11 @@ and TASM: a multi-line macro definition in NASM looks something like
|
|||
this.
|
||||
|
||||
\c %macro prologue 1
|
||||
\c
|
||||
\c push ebp
|
||||
\c mov ebp,esp
|
||||
\c sub esp,%1
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This defines a C-like function prologue as a macro: so you would
|
||||
|
@ -1845,8 +1860,11 @@ in \I{braces, around macro parameters}braces. So you could code
|
|||
things like
|
||||
|
||||
\c %macro silly 2
|
||||
\c
|
||||
\c %2: db %1
|
||||
\c
|
||||
\c %endmacro
|
||||
\c
|
||||
\c silly 'a', letter_a ; letter_a: db 'a'
|
||||
\c silly 'ab', string_ab ; string_ab: db 'ab'
|
||||
\c silly {13,10}, crlf ; crlf: db 13,10
|
||||
|
@ -1860,8 +1878,10 @@ parameters. This time, no exception is made for macros with no
|
|||
parameters at all. So you could define
|
||||
|
||||
\c %macro prologue 0
|
||||
\c
|
||||
\c push ebp
|
||||
\c mov ebp,esp
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
to define an alternative form of the function prologue which
|
||||
|
@ -1871,8 +1891,10 @@ Sometimes, however, you might want to `overload' a machine
|
|||
instruction; for example, you might want to define
|
||||
|
||||
\c %macro push 2
|
||||
\c
|
||||
\c push %1
|
||||
\c push %2
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
so that you could code
|
||||
|
@ -1898,9 +1920,11 @@ you can invent an instruction which executes a \c{RET} if the \c{Z}
|
|||
flag is set by doing this:
|
||||
|
||||
\c %macro retz 0
|
||||
\c
|
||||
\c jnz %%skip
|
||||
\c ret
|
||||
\c %%skip:
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
You can call this macro as many times as you want, and every time
|
||||
|
@ -1931,13 +1955,16 @@ the last defined one along with the separating commas. So if you
|
|||
code:
|
||||
|
||||
\c %macro writefile 2+
|
||||
\c
|
||||
\c jmp %%endstr
|
||||
\c %%str: db %2
|
||||
\c %%endstr: mov dx,%%str
|
||||
\c %%endstr:
|
||||
\c mov dx,%%str
|
||||
\c mov cx,%%endstr-%%str
|
||||
\c mov bx,%1
|
||||
\c mov ah,0x40
|
||||
\c int 0x21
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
then the example call to \c{writefile} above will work as expected:
|
||||
|
@ -1979,9 +2006,11 @@ of allowable parameter counts. If you do this, you can specify
|
|||
defaults for \i{omitted parameters}. So, for example:
|
||||
|
||||
\c %macro die 0-1 "Painful program death has occurred."
|
||||
\c
|
||||
\c writefile 2,%1
|
||||
\c mov ax,0x4c01
|
||||
\c int 0x21
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This macro (which makes use of the \c{writefile} macro defined in
|
||||
|
@ -2051,10 +2080,12 @@ parameters are rotated to the right.
|
|||
restore a set of registers might work as follows:
|
||||
|
||||
\c %macro multipush 1-*
|
||||
\c
|
||||
\c %rep %0
|
||||
\c push %1
|
||||
\c %rotate 1
|
||||
\c %endrep
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This macro invokes the \c{PUSH} instruction on each of its arguments
|
||||
|
@ -2080,10 +2111,12 @@ order from the one in which they were pushed.
|
|||
This can be done by the following definition:
|
||||
|
||||
\c %macro multipop 1-*
|
||||
\c
|
||||
\c %rep %0
|
||||
\c %rotate -1
|
||||
\c pop %1
|
||||
\c %endrep
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This macro begins by rotating its arguments one place to the
|
||||
|
@ -2102,9 +2135,12 @@ table of key codes along with offsets into the table, you could code
|
|||
something like
|
||||
|
||||
\c %macro keytab_entry 2
|
||||
\c
|
||||
\c keypos%1 equ $-keytab
|
||||
\c db %2
|
||||
\c
|
||||
\c %endmacro
|
||||
\c
|
||||
\c keytab:
|
||||
\c keytab_entry F1,128+1
|
||||
\c keytab_entry F2,128+2
|
||||
|
@ -2159,9 +2195,11 @@ condition code. So the \c{retz} macro defined in \k{maclocal} can be
|
|||
replaced by a general \i{conditional-return macro} like this:
|
||||
|
||||
\c %macro retc 1
|
||||
\c
|
||||
\c j%-1 %%skip
|
||||
\c ret
|
||||
\c %%skip:
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This macro can now be invoked using calls like \c{retc ne}, which
|
||||
|
@ -2239,6 +2277,42 @@ definitions in \c{%elif} blocks by using \i\c{%elifdef} and
|
|||
\i\c{%elifndef}.
|
||||
|
||||
|
||||
\S{ifmacro} \i\c{ifmacro}: \i{Testing Multi-Line Macro Existence}
|
||||
|
||||
The \c{%ifmacro} directive oeprates in the same way as the \c{%ifdef}
|
||||
directive, except that it checks for the existence of a multi-line macro.
|
||||
|
||||
For example, you may be working with a large project and not have control
|
||||
over the macros in a library. You may want to create a macro with one
|
||||
name if it doesn't already exist, and another name if one with that name
|
||||
does exist.
|
||||
|
||||
The %ifmacro is considered true if defining a macro with the given name
|
||||
and number of arguements would cause a definitions conflict. For example:
|
||||
|
||||
\c %ifmacro MyMacro 1-3
|
||||
\c
|
||||
\c %error "MyMacro 1-3" causes a conflict with an existing macro.
|
||||
\c
|
||||
\c %else
|
||||
\c
|
||||
\c %macro MyMacro 1-3
|
||||
\c
|
||||
\c ; insert code to define the macro
|
||||
\c
|
||||
\c %endmacro
|
||||
\c
|
||||
\c %endif
|
||||
|
||||
This will create the macro "MyMacro 1-3" if no macro already exists which
|
||||
would conflict with it, and emits a warning if there would be a definition
|
||||
conflict.
|
||||
|
||||
You can test for the macro not existing by using the \i\c{ifnmacro} instead
|
||||
of \c{ifmacro}. Additional tests can be performed in %elif blocks by using
|
||||
\i\c{elifmacro} and \i\c{elifnmacro}.
|
||||
|
||||
|
||||
\S{ifctx} \i\c{%ifctx}: \i{Testing the Context Stack}
|
||||
|
||||
The conditional-assembly construct \c{%ifctx ctxname} will cause the
|
||||
|
@ -2292,12 +2366,14 @@ For example, the following macro pushes a register or number on the
|
|||
stack, and allows you to treat \c{IP} as a real register:
|
||||
|
||||
\c %macro pushparam 1
|
||||
\c
|
||||
\c %ifidni %1,ip
|
||||
\c call %%label
|
||||
\c %%label:
|
||||
\c %else
|
||||
\c push %1
|
||||
\c %endif
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
Like most other \c{%if} constructs, \c{%ifidn} has a counterpart
|
||||
|
@ -2325,6 +2401,7 @@ For example, the \c{writefile} macro defined in \k{mlmacgre} can be
|
|||
extended to take advantage of \c{%ifstr} in the following fashion:
|
||||
|
||||
\c %macro writefile 2-3+
|
||||
\c
|
||||
\c %ifstr %2
|
||||
\c jmp %%endstr
|
||||
\c %if %0 = 3
|
||||
|
@ -2341,6 +2418,7 @@ extended to take advantage of \c{%ifstr} in the following fashion:
|
|||
\c mov bx,%1
|
||||
\c mov ah,0x40
|
||||
\c int 0x21
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
Then the \c{writefile} macro can cope with being called in either of
|
||||
|
@ -2425,6 +2503,7 @@ terminate the loop, like this:
|
|||
\c %assign i j
|
||||
\c %assign j k
|
||||
\c %endrep
|
||||
\c
|
||||
\c fib_number equ ($-fibonacci)/2
|
||||
|
||||
This produces a list of all the Fibonacci numbers that will fit in
|
||||
|
@ -2514,13 +2593,17 @@ of the context stack. So the \c{REPEAT} and \c{UNTIL} example given
|
|||
above could be implemented by means of:
|
||||
|
||||
\c %macro repeat 0
|
||||
\c
|
||||
\c %push repeat
|
||||
\c %$begin:
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
\c
|
||||
\c %macro until 1
|
||||
\c
|
||||
\c j%-1 %$begin
|
||||
\c %pop
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
and invoked by means of, for example,
|
||||
|
@ -2576,11 +2659,14 @@ including the conditional-assembly construct \i\c{%ifctx}, to
|
|||
implement a block IF statement as a set of macros.
|
||||
|
||||
\c %macro if 1
|
||||
\c
|
||||
\c %push if
|
||||
\c j%-1 %$ifnot
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
\c
|
||||
\c %macro else 0
|
||||
\c
|
||||
\c %ifctx if
|
||||
\c %repl else
|
||||
\c jmp %$ifend
|
||||
|
@ -2588,9 +2674,11 @@ implement a block IF statement as a set of macros.
|
|||
\c %else
|
||||
\c %error "expected `if' before `else'"
|
||||
\c %endif
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
\c
|
||||
\c %macro endif 0
|
||||
\c
|
||||
\c %ifctx if
|
||||
\c %$ifnot:
|
||||
\c %pop
|
||||
|
@ -2600,6 +2688,7 @@ implement a block IF statement as a set of macros.
|
|||
\c %else
|
||||
\c %error "expected `if' or `else' before `endif'"
|
||||
\c %endif
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This code is more robust than the \c{REPEAT} and \c{UNTIL} macros
|
||||
|
@ -2623,18 +2712,23 @@ intervening \c{else}. It does this by the use of \c{%repl}.
|
|||
A sample usage of these macros might look like:
|
||||
|
||||
\c cmp ax,bx
|
||||
\c
|
||||
\c if ae
|
||||
\c cmp bx,cx
|
||||
\c
|
||||
\c if ae
|
||||
\c mov ax,cx
|
||||
\c else
|
||||
\c mov ax,bx
|
||||
\c endif
|
||||
\c
|
||||
\c else
|
||||
\c cmp ax,cx
|
||||
\c
|
||||
\c if ae
|
||||
\c mov ax,cx
|
||||
\c endif
|
||||
\c
|
||||
\c endif
|
||||
|
||||
The block-\c{IF} macros handle nesting quite happily, by means of
|
||||
|
@ -2685,10 +2779,12 @@ line number in \c{EAX} and outputs something like `line 155: still
|
|||
here'. You could then write a macro
|
||||
|
||||
\c %macro notdeadyet 0
|
||||
\c
|
||||
\c push eax
|
||||
\c mov eax,__LINE__
|
||||
\c call stillhere
|
||||
\c pop eax
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
and then pepper your code with calls to \c{notdeadyet} until you
|
||||
|
@ -2714,10 +2810,12 @@ For example, to define a structure called \c{mytype} containing a
|
|||
longword, a word, a byte and a string of bytes, you might code
|
||||
|
||||
\c struc mytype
|
||||
\c
|
||||
\c mt_long: resd 1
|
||||
\c mt_word: resw 1
|
||||
\c mt_byte: resb 1
|
||||
\c mt_str: resb 32
|
||||
\c
|
||||
\c endstruc
|
||||
|
||||
The above code defines six symbols: \c{mt_long} as 0 (the offset
|
||||
|
@ -2731,10 +2829,12 @@ mechanism: if your structure members tend to have the same names in
|
|||
more than one structure, you can define the above structure like this:
|
||||
|
||||
\c struc mytype
|
||||
\c
|
||||
\c .long: resd 1
|
||||
\c .word: resw 1
|
||||
\c .byte: resb 1
|
||||
\c .str: resb 32
|
||||
\c
|
||||
\c endstruc
|
||||
|
||||
This defines the offsets to the structure fields as \c{mytype.long},
|
||||
|
@ -2758,11 +2858,14 @@ segment. NASM provides an easy way to do this in the \c{ISTRUC}
|
|||
mechanism. To declare a structure of type \c{mytype} in a program,
|
||||
you code something like this:
|
||||
|
||||
\c mystruc: istruc mytype
|
||||
\c mystruc:
|
||||
\c istruc mytype
|
||||
\c
|
||||
\c at mt_long, dd 123456
|
||||
\c at mt_word, dw 1024
|
||||
\c at mt_byte, db 'x'
|
||||
\c at mt_str, db 'hello, world', 13, 10, 0
|
||||
\c
|
||||
\c iend
|
||||
|
||||
The function of the \c{AT} macro is to make use of the \c{TIMES}
|
||||
|
@ -2823,12 +2926,18 @@ thing.
|
|||
be used within structure definitions:
|
||||
|
||||
\c struc mytype2
|
||||
\c mt_byte: resb 1
|
||||
\c
|
||||
\c mt_byte:
|
||||
\c resb 1
|
||||
\c alignb 2
|
||||
\c mt_word: resw 1
|
||||
\c mt_word:
|
||||
\c resw 1
|
||||
\c alignb 4
|
||||
\c mt_long: resd 1
|
||||
\c mt_str: resb 32
|
||||
\c mt_long:
|
||||
\c resd 1
|
||||
\c mt_str:
|
||||
\c resb 32
|
||||
\c
|
||||
\c endstruc
|
||||
|
||||
This will ensure that the structure members are sensibly aligned
|
||||
|
@ -2868,13 +2977,16 @@ convenient to use and is not TASM compatible. Here is an example
|
|||
which shows the use of \c{%arg} without any external macros:
|
||||
|
||||
\c some_function:
|
||||
\c
|
||||
\c %push mycontext ; save the current context
|
||||
\c %stacksize large ; tell NASM to use bp
|
||||
\c %arg i:word, j_ptr:word
|
||||
\c
|
||||
\c mov ax,[i]
|
||||
\c mov bx,[j_ptr]
|
||||
\c add ax,[bx]
|
||||
\c ret
|
||||
\c
|
||||
\c %pop ; restore original context
|
||||
|
||||
This is similar to the procedure defined in \k{16cmacro} and adds
|
||||
|
@ -2928,10 +3040,12 @@ instruction (see \k{insENTER} for a description of that instruction).
|
|||
An example of its use is the following:
|
||||
|
||||
\c silly_swap:
|
||||
\c
|
||||
\c %push mycontext ; save the current context
|
||||
\c %stacksize small ; tell NASM to use bp
|
||||
\c %assign %$localsize 0 ; see text for explanation
|
||||
\c %local old_ax:word, old_dx:word
|
||||
\c
|
||||
\c enter %$localsize,0 ; see text for explanation
|
||||
\c mov [old_ax],ax ; swap ax & bx
|
||||
\c mov [old_dx],dx ; and swap dx & cx
|
||||
|
@ -2941,6 +3055,7 @@ An example of its use is the following:
|
|||
\c mov cx,[old_dx]
|
||||
\c leave ; restore old bp
|
||||
\c ret ;
|
||||
\c
|
||||
\c %pop ; restore original context
|
||||
|
||||
The \c{%$localsize} variable is used internally by the
|
||||
|
@ -3061,15 +3176,20 @@ For example, the \c{writefile} macro defined in \k{mlmacgre} can be
|
|||
usefully rewritten in the following more sophisticated form:
|
||||
|
||||
\c %macro writefile 2+
|
||||
\c
|
||||
\c [section .data]
|
||||
\c
|
||||
\c %%str: db %2
|
||||
\c %%endstr:
|
||||
\c
|
||||
\c __SECT__
|
||||
\c
|
||||
\c mov dx,%%str
|
||||
\c mov cx,%%endstr-%%str
|
||||
\c mov bx,%1
|
||||
\c mov ah,0x40
|
||||
\c int 0x21
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
This form of the macro, once passed a string to output, first
|
||||
|
@ -3095,6 +3215,7 @@ mode are the \c{RESB} family.
|
|||
\c{ABSOLUTE} is used as follows:
|
||||
|
||||
\c absolute 0x1A
|
||||
\c
|
||||
\c kbuf_chr resw 1
|
||||
\c kbuf_free resw 1
|
||||
\c kbuf resw 16
|
||||
|
@ -3115,12 +3236,18 @@ expression}: see \k{crit}) and it can be a value in a segment. For
|
|||
example, a TSR can re-use its setup code as run-time BSS like this:
|
||||
|
||||
\c org 100h ; it's a .COM program
|
||||
\c
|
||||
\c jmp setup ; setup code comes last
|
||||
\c
|
||||
\c ; the resident part of the TSR goes here
|
||||
\c setup: ; now write the code that installs the TSR here
|
||||
\c setup:
|
||||
\c ; now write the code that installs the TSR here
|
||||
\c
|
||||
\c absolute setup
|
||||
\c
|
||||
\c runtimevar1 resw 1
|
||||
\c runtimevar2 resd 20
|
||||
\c
|
||||
\c tsr_end:
|
||||
|
||||
This defines some variables `on top of' the setup code, so that
|
||||
|
@ -3179,7 +3306,8 @@ refer to symbols which \e{are} defined in the same module as the
|
|||
\c{GLOBAL} directive. For example:
|
||||
|
||||
\c global _main
|
||||
\c _main: ; some code
|
||||
\c _main:
|
||||
\c ; some code
|
||||
|
||||
\c{GLOBAL}, like \c{EXTERN}, allows object formats to define private
|
||||
extensions by means of a colon. The \c{elf} object format, for
|
||||
|
@ -3205,6 +3333,7 @@ is similar in function to
|
|||
|
||||
\c global intvar
|
||||
\c section .bss
|
||||
\c
|
||||
\c intvar resd 1
|
||||
|
||||
The difference is that if more than one module defines the same
|
||||
|
@ -3246,11 +3375,11 @@ Options are:
|
|||
|
||||
\b\c{CPU PENTIUM} Same as 586
|
||||
|
||||
\b\c{CPU 686} Pentium Pro instruction set
|
||||
\b\c{CPU 686} P6 instruction set
|
||||
|
||||
\b\c{CPU PPRO} Same as 686
|
||||
|
||||
\b\c{CPU P2} Pentium II instruction set
|
||||
\b\c{CPU P2} Same as 686
|
||||
|
||||
\b\c{CPU P3} Pentium III and Katmai instruction sets
|
||||
|
||||
|
@ -3382,9 +3511,13 @@ segment name as a symbol as well, so that you can access the segment
|
|||
address of the segment. So, for example:
|
||||
|
||||
\c segment data
|
||||
\c
|
||||
\c dvar: dw 1234
|
||||
\c
|
||||
\c segment code
|
||||
\c function: mov ax,data ; get segment address of data
|
||||
\c
|
||||
\c function:
|
||||
\c mov ax,data ; get segment address of data
|
||||
\c mov ds,ax ; and move it into DS
|
||||
\c inc word [dvar] ; now this reference will work
|
||||
\c ret
|
||||
|
@ -3394,6 +3527,7 @@ The \c{obj} format also enables the use of the \i\c{SEG} and
|
|||
like
|
||||
|
||||
\c extern foo
|
||||
\c
|
||||
\c mov ax,seg foo ; get preferred segment of foo
|
||||
\c mov ds,ax
|
||||
\c mov ax,data ; a different segment
|
||||
|
@ -3473,9 +3607,13 @@ a group. NASM therefore supplies the \c{GROUP} directive, whereby
|
|||
you can code
|
||||
|
||||
\c segment data
|
||||
\c
|
||||
\c ; some data
|
||||
\c
|
||||
\c segment bss
|
||||
\c
|
||||
\c ; some uninitialised data
|
||||
\c
|
||||
\c group dgroup data bss
|
||||
|
||||
which will define a group called \c{dgroup} to contain the segments
|
||||
|
@ -3901,6 +4039,7 @@ symbol, as a numeric expression (which may involve labels, and even
|
|||
forward references) after the type specifier. Like this:
|
||||
|
||||
\c global hashtable:data (hashtable.end - hashtable)
|
||||
\c
|
||||
\c hashtable:
|
||||
\c db this,that,theother ; some data here
|
||||
\c .end:
|
||||
|
@ -3913,8 +4052,8 @@ writing shared library code. For more information, see
|
|||
\k{picglobal}.
|
||||
|
||||
|
||||
\S{elfcomm} \c{elf} Extensions to the \c{COMMON} Directive\I{COMMON,
|
||||
elf extensions to}
|
||||
\S{elfcomm} \c{elf} Extensions to the \c{COMMON} Directive
|
||||
\I{COMMON, elf extensions to}
|
||||
|
||||
\c{ELF} also allows you to specify alignment requirements \I{common
|
||||
variables, alignment in elf}\I{alignment, of elf common variables}on
|
||||
|
@ -4175,7 +4314,8 @@ the NASM archives, under the name \c{objexe.asm}.
|
|||
|
||||
\c segment code
|
||||
\c
|
||||
\c ..start: mov ax,data
|
||||
\c ..start:
|
||||
\c mov ax,data
|
||||
\c mov ds,ax
|
||||
\c mov ax,stack
|
||||
\c mov ss,ax
|
||||
|
@ -4208,6 +4348,7 @@ full pointer is valid), and call the DOS print-string function.
|
|||
This terminates the program using another DOS system call.
|
||||
|
||||
\c segment data
|
||||
\c
|
||||
\c hello: db 'hello, world', 13, 10, '$'
|
||||
|
||||
The data segment contains the string we want to display.
|
||||
|
@ -4293,11 +4434,18 @@ write a \c{.COM} program, you would create a source file looking
|
|||
like
|
||||
|
||||
\c org 100h
|
||||
\c
|
||||
\c section .text
|
||||
\c start: ; put your code here
|
||||
\c
|
||||
\c start:
|
||||
\c ; put your code here
|
||||
\c
|
||||
\c section .data
|
||||
\c
|
||||
\c ; put data items here
|
||||
\c
|
||||
\c section .bss
|
||||
\c
|
||||
\c ; put uninitialised data here
|
||||
|
||||
The \c{bin} format puts the \c{.text} section first in the file, so
|
||||
|
@ -4395,13 +4543,17 @@ If you find the underscores inconvenient, you can define macros to
|
|||
replace the \c{GLOBAL} and \c{EXTERN} directives as follows:
|
||||
|
||||
\c %macro cglobal 1
|
||||
\c
|
||||
\c global _%1
|
||||
\c %define %1 _%1
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
\c
|
||||
\c %macro cextern 1
|
||||
\c
|
||||
\c extern _%1
|
||||
\c %define %1 _%1
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
(These forms of the macros only take one argument at a time; a
|
||||
|
@ -4563,11 +4715,15 @@ Thus, you would define a function in C style in the following way.
|
|||
The following example is for small model:
|
||||
|
||||
\c global _myfunc
|
||||
\c _myfunc: push bp
|
||||
\c
|
||||
\c _myfunc:
|
||||
\c push bp
|
||||
\c mov bp,sp
|
||||
\c sub sp,0x40 ; 64 bytes of local stack space
|
||||
\c mov bx,[bp+4] ; first parameter to function
|
||||
\c
|
||||
\c ; some more code
|
||||
\c
|
||||
\c mov sp,bp ; undo "sub sp,0x40" above
|
||||
\c pop bp
|
||||
\c ret
|
||||
|
@ -4583,13 +4739,18 @@ At the other end of the process, to call a C function from your
|
|||
assembly code, you would do something like this:
|
||||
|
||||
\c extern _printf
|
||||
\c
|
||||
\c ; and then, further down...
|
||||
\c
|
||||
\c push word [myint] ; one of my integer variables
|
||||
\c push word mystring ; pointer into my data segment
|
||||
\c call _printf
|
||||
\c add sp,byte 4 ; `byte' saves space
|
||||
\c
|
||||
\c ; then those data items...
|
||||
\c
|
||||
\c segment _DATA
|
||||
\c
|
||||
\c myint dw 1234
|
||||
\c mystring db 'This number -> %d <- should be 1234',10,0
|
||||
|
||||
|
@ -4632,6 +4793,7 @@ in \k{16cunder}.) Thus, a C variable declared as \c{int i} can be
|
|||
accessed from assembler as
|
||||
|
||||
\c extern _i
|
||||
\c
|
||||
\c mov ax,[_i]
|
||||
|
||||
And to declare your own integer variable which C programs can access
|
||||
|
@ -4639,6 +4801,7 @@ as \c{extern int j}, you do this (making sure you are assembling in
|
|||
the \c{_DATA} segment, if necessary):
|
||||
|
||||
\c global _j
|
||||
\c
|
||||
\c _j dw 0
|
||||
|
||||
To access a C array, you need to know the size of the components of
|
||||
|
@ -4689,11 +4852,13 @@ An example of an assembly function using the macro set is given
|
|||
here:
|
||||
|
||||
\c proc _nearproc
|
||||
\c
|
||||
\c %$i arg
|
||||
\c %$j arg
|
||||
\c mov ax,[bp + %$i]
|
||||
\c mov bx,[bp + %$j]
|
||||
\c add ax,[bx]
|
||||
\c
|
||||
\c endproc
|
||||
|
||||
This defines \c{_nearproc} to be a procedure taking two arguments,
|
||||
|
@ -4723,13 +4888,16 @@ many function parameters will be of type \c{int}.
|
|||
The large-model equivalent of the above function would look like this:
|
||||
|
||||
\c %define FARCODE
|
||||
\c
|
||||
\c proc _farproc
|
||||
\c
|
||||
\c %$i arg
|
||||
\c %$j arg 4
|
||||
\c mov ax,[bp + %$i]
|
||||
\c mov bx,[bp + %$j]
|
||||
\c mov es,[bp + %$j + 2]
|
||||
\c add ax,[bx]
|
||||
\c
|
||||
\c endproc
|
||||
|
||||
This makes use of the argument to the \c{arg} macro to define a
|
||||
|
@ -4830,12 +4998,15 @@ Thus, you would define a function in Pascal style, taking two
|
|||
\c{Integer}-type parameters, in the following way:
|
||||
|
||||
\c global myfunc
|
||||
\c
|
||||
\c myfunc: push bp
|
||||
\c mov bp,sp
|
||||
\c sub sp,0x40 ; 64 bytes of local stack space
|
||||
\c mov bx,[bp+8] ; first parameter to function
|
||||
\c mov bx,[bp+6] ; second parameter to function
|
||||
\c
|
||||
\c ; some more code
|
||||
\c
|
||||
\c mov sp,bp ; undo "sub sp,0x40" above
|
||||
\c pop bp
|
||||
\c retf 4 ; total size of params is 4
|
||||
|
@ -4844,7 +5015,9 @@ At the other end of the process, to call a Pascal function from your
|
|||
assembly code, you would do something like this:
|
||||
|
||||
\c extern SomeFunc
|
||||
\c
|
||||
\c ; and then, further down...
|
||||
\c
|
||||
\c push word seg mystring ; Now push the segment, and...
|
||||
\c push word mystring ; ... offset of "mystring"
|
||||
\c push word [myint] ; one of my variables
|
||||
|
@ -4893,13 +5066,16 @@ argument offsets; you must declare your function's arguments in
|
|||
reverse order. For example:
|
||||
|
||||
\c %define PASCAL
|
||||
\c
|
||||
\c proc _pascalproc
|
||||
\c
|
||||
\c %$j arg 4
|
||||
\c %$i arg
|
||||
\c mov ax,[bp + %$i]
|
||||
\c mov bx,[bp + %$j]
|
||||
\c mov es,[bp + %$j + 2]
|
||||
\c add ax,[bx]
|
||||
\c
|
||||
\c endproc
|
||||
|
||||
This defines the same routine, conceptually, as the example in
|
||||
|
@ -5027,11 +5203,15 @@ still pushed in right-to-left order.
|
|||
Thus, you would define a function in C style in the following way:
|
||||
|
||||
\c global _myfunc
|
||||
\c _myfunc: push ebp
|
||||
\c
|
||||
\c _myfunc:
|
||||
\c push ebp
|
||||
\c mov ebp,esp
|
||||
\c sub esp,0x40 ; 64 bytes of local stack space
|
||||
\c mov ebx,[ebp+8] ; first parameter to function
|
||||
\c
|
||||
\c ; some more code
|
||||
\c
|
||||
\c leave ; mov esp,ebp / pop ebp
|
||||
\c ret
|
||||
|
||||
|
@ -5039,13 +5219,18 @@ At the other end of the process, to call a C function from your
|
|||
assembly code, you would do something like this:
|
||||
|
||||
\c extern _printf
|
||||
\c
|
||||
\c ; and then, further down...
|
||||
\c
|
||||
\c push dword [myint] ; one of my integer variables
|
||||
\c push dword mystring ; pointer into my data segment
|
||||
\c call _printf
|
||||
\c add esp,byte 8 ; `byte' saves space
|
||||
\c
|
||||
\c ; then those data items...
|
||||
\c
|
||||
\c segment _DATA
|
||||
\c
|
||||
\c myint dd 1234
|
||||
\c mystring db 'This number -> %d <- should be 1234',10,0
|
||||
|
||||
|
@ -5119,11 +5304,13 @@ An example of an assembly function using the macro set is given
|
|||
here:
|
||||
|
||||
\c proc _proc32
|
||||
\c
|
||||
\c %$i arg
|
||||
\c %$j arg
|
||||
\c mov eax,[ebp + %$i]
|
||||
\c mov ebx,[ebp + %$j]
|
||||
\c add eax,[ebx]
|
||||
\c
|
||||
\c endproc
|
||||
|
||||
This defines \c{_proc32} to be a procedure taking two arguments, the
|
||||
|
@ -5200,9 +5387,12 @@ in this form:
|
|||
\c mov ebp,esp
|
||||
\c push ebx
|
||||
\c call .get_GOT
|
||||
\c .get_GOT: pop ebx
|
||||
\c .get_GOT:
|
||||
\c pop ebx
|
||||
\c add ebx,_GLOBAL_OFFSET_TABLE_+$$-.get_GOT wrt ..gotpc
|
||||
\c
|
||||
\c ; the function body comes here
|
||||
\c
|
||||
\c mov ebx,[ebp-4]
|
||||
\c mov esp,ebp
|
||||
\c pop ebp
|
||||
|
@ -5239,9 +5429,12 @@ obtain the address of the GOT by any other means, so you can put
|
|||
those three instructions into a macro and safely ignore them:
|
||||
|
||||
\c %macro get_GOT 0
|
||||
\c
|
||||
\c call %%getgot
|
||||
\c %%getgot: pop ebx
|
||||
\c %%getgot:
|
||||
\c pop ebx
|
||||
\c add ebx,_GLOBAL_OFFSET_TABLE_+$$-%%getgot wrt ..gotpc
|
||||
\c
|
||||
\c %endmacro
|
||||
|
||||
\S{piclocal} Finding Your Local Data Items
|
||||
|
@ -5307,12 +5500,15 @@ declared.
|
|||
So to export a function to users of the library, you must use
|
||||
|
||||
\c global func:function ; declare it as a function
|
||||
\c
|
||||
\c func: push ebp
|
||||
\c
|
||||
\c ; etc.
|
||||
|
||||
And to export a data item such as an array, you would have to code
|
||||
|
||||
\c global array:data array.end-array ; give the size too
|
||||
\c
|
||||
\c array: resd 128
|
||||
\c .end:
|
||||
|
||||
|
@ -5610,7 +5806,9 @@ place the \c{0xAA55} signature word at the end of a 512-byte boot
|
|||
sector, people who are used to MASM tend to code
|
||||
|
||||
\c ORG 0
|
||||
\c
|
||||
\c ; some boot sector code
|
||||
\c
|
||||
\c ORG 510
|
||||
\c DW 0xAA55
|
||||
|
||||
|
@ -5619,7 +5817,9 @@ will not work. The correct way to solve this problem in NASM is to
|
|||
use the \i\c{TIMES} directive, like this:
|
||||
|
||||
\c ORG 0
|
||||
\c
|
||||
\c ; some boot sector code
|
||||
\c
|
||||
\c TIMES 510-($-$$) DB 0
|
||||
\c DW 0xAA55
|
||||
|
||||
|
@ -6188,45 +6388,45 @@ The instructions that use this will give details of what the various
|
|||
mnemonics are, this table is used to help you work out details of what
|
||||
is happening.
|
||||
|
||||
Predi- imm8 Description Relation where: Emula- Result if QNaN
|
||||
cate Encod- A Is 1st Operand tion NaN Signals
|
||||
ing B Is 2nd Operand Operand Invalid
|
||||
|
||||
EQ 000B equal A = B False No
|
||||
|
||||
LT 001B less-than A < B False Yes
|
||||
|
||||
LE 010B less-than- A <= B False Yes
|
||||
or-equal
|
||||
|
||||
--- ---- greater A > B Swap False Yes
|
||||
than Operands,
|
||||
Use LT
|
||||
|
||||
--- ---- greater- A >= B Swap False Yes
|
||||
than-or-equal Operands,
|
||||
Use LE
|
||||
|
||||
UNORD 011B unordered A, B = Unordered True No
|
||||
|
||||
NEQ 100B not-equal A != B True No
|
||||
|
||||
NLT 101B not-less- NOT(A < B) True Yes
|
||||
than
|
||||
|
||||
NLE 110B not-less- NOT(A <= B) True Yes
|
||||
than-or-
|
||||
equal
|
||||
|
||||
--- ---- not-greater NOT(A > B) Swap True Yes
|
||||
than Operands,
|
||||
Use NLT
|
||||
|
||||
--- ---- not-greater NOT(A >= B) Swap True Yes
|
||||
than- Operands,
|
||||
or-equal Use NLE
|
||||
|
||||
ORD 111B ordered A , B = Ordered False No
|
||||
\c Predi- imm8 Description Relation where: Emula- Result QNaN
|
||||
\c cate Encod- A Is 1st Operand tion if NaN Signal
|
||||
\c ing B Is 2nd Operand Operand Invalid
|
||||
\c
|
||||
\c EQ 000B equal A = B False No
|
||||
\c
|
||||
\c LT 001B less-than A < B False Yes
|
||||
\c
|
||||
\c LE 010B less-than- A <= B False Yes
|
||||
\c or-equal
|
||||
\c
|
||||
\c --- ---- greater A > B Swap False Yes
|
||||
\c than Operands,
|
||||
\c Use LT
|
||||
\c
|
||||
\c --- ---- greater- A >= B Swap False Yes
|
||||
\c than-or-equal Operands,
|
||||
\c Use LE
|
||||
\c
|
||||
\c UNORD 011B unordered A, B = Unordered True No
|
||||
\c
|
||||
\c NEQ 100B not-equal A != B True No
|
||||
\c
|
||||
\c NLT 101B not-less- NOT(A < B) True Yes
|
||||
\c than
|
||||
\c
|
||||
\c NLE 110B not-less- NOT(A <= B) True Yes
|
||||
\c than-or-
|
||||
\c equal
|
||||
\c
|
||||
\c --- ---- not-greater NOT(A > B) Swap True Yes
|
||||
\c than Operands,
|
||||
\c Use NLT
|
||||
\c
|
||||
\c --- ---- not-greater NOT(A >= B) Swap True Yes
|
||||
\c than- Operands,
|
||||
\c or-equal Use NLE
|
||||
\c
|
||||
\c ORD 111B ordered A , B = Ordered False No
|
||||
|
||||
The unordered relationship is true when at least one of the two
|
||||
values being compared is a NaN or in an unsupported format.
|
||||
|
|
Loading…
Reference in a new issue