APPENDIX: ASSEMBLER inserts
Updated: Sep 3, 2008

Please see Statements > Advanced Techniques > ASM statement.
An ASM insert defaults to the .CODE section of your program.

ASM Statement Syntax:

1. Comments are removed (";").
2. Statements are trimmed of leading/trailing spaces (TRIM$).
3. Then only one space is allowed and that after the opcode.

Examples:

  ASM mov eax,1
  ASM push i
  ASM lea esi,i
  ASM finit  ;has no operands and no spaces

Note:  With use of a BEGIN ASM/END ASM code block, one can drop the "ASM "
prefix in the examples above.

4. Supported operands/addressing:

Description ... Example
[x]             inc i
x               push 10
r               inc eax
[r]             inc [esi]
r,[x]           mov edx,i
r,x             mov edx,10
r,r             mov eax,edx
r,[r]           mov eax,[esi]
[x],x           mov i,10
[x],r           mov i,eax
[r],r           mov [esi],eax

Notes:
[x] is a 8, 16 or 32 bit variable (e.g., dim i as long).
x is a decimal (as above) or hex number.
Hex numbers all start with 0-9 and end with "h" or "H":
  0Ah ;is 10
  8h  ;is 8
  0ffffffffh ;is -1
[r] above may be [r] or [r+x] or [r-x] where +x <=127 and -x >=
  -128 -- that is, a signed byte.  Examples:

  ASM push ebx
  ASM push [ebx]
  ASM push [ebx+8]
  ASM mov [ebx+8],eax

[esp] syntax is not supported for the esp register; however, one can

  ASM mov ebx,esp   ;get stack pointer
  ASM mov eax,[ebx] ;get stack value

5. Supported directives include

.IF
.ELSE
.ENDIF
.DATA
.DATA?
.CODE
INVOKE
INCLUDE {pathname}      ;asm source code to be inserted
INCLUDECODE {pathname}  ;binary file content pasted into .CODE section
INCLUDEDATA {pathname}  ;binary file content pasted into .DATA section
INCLUDELIB {pathname}   ;add pathname to link.exe commands

Notice that INCLUDELIB may be viewed as "INCLUDECOMMAND" since a link switch
might also be specified:  ASM INCLUDELIB "-fixed:no"

An exception to the one-space only syntax, is the use of ADDR in INVOKE:

  ASM INVOKE SomeProcedure,0,ADDR i

where the address of i is pushed on to the stack as the second argument (first
pushed).

For .IF, the argument is a single register or variable which may be preceded
by "!" (not).  Examples:

  ASM .IF eax  ;true if eax<>0
  ASM .IF !eax ;true if eax=0
  ASM .IF i
  ASM .IF !i

More complicated "conditional expressions" can be written in code to reduce
them to a single zero or non-zero item for .IF.

6. Labels are the same as in your HotBasic code -- a source code line with your
label symbol punctuated with ":"

  ASM mov ecx,10  ;loop 10 times
  ASM Next_Thing: ;statement label
  ASM ;code in loop
  ASM dec ecx
  ASM jg Next_Thing

You may transfer control to a label either in HotBasic code or in an ASM
insert, as above.

7. Auto-generation of labels.  Forward jmps (conditional or unconditional) are
supported.  Example:

  ASM jg @F
  ASM ;more asm statements here
  ASM @@:

Above "@@:" will auto-generate a label to which "@F" refers.

8. You may create .DATA blocks as follows, noting that these symbols cannot
duplicate any already defined in HotBasic code and will be usable only in ASM
inserts, not in HotBasic code.  Example:

  ASM .DATA       ;switch to .DATA section
  ASM MyVar dd 0  ;allocate MyVar as dword
  ASM .CODE       ;back to .CODE section

Valid data types for ASM inserts:

Symbol ... Description
db         byte
byte       byte
word       word
dd         dword
dword      dword
qword      8 bytes
tbyte      10 bytes
real10     10 bytes

Examples:

  ASM .DATA
  ASM MyStr db "HotBasic Power",0
  ASM MyBytes db 1,10,200,5
  ASM MyDD dd 0
  ASM MyFloat tbyte 2.5
  ASM MyType dd 40,1000h,5,4000h,6 dup(0)
  ASM .CODE

If you switch to the .DATA section, do not forget to return to the .CODE
section!

9. Inserting binary values in the .CODE section.

  ASM db 255,115,4  ;push [ebx+4]

The insert above is equivalent to a "push [ebx+4]" statement.  HotBasic ASM
inserts support this statement, so there is no need to directly insert binary
values as above.  One can just write

  ASM push [ebx+4]

However, statements with "ptr" syntax -- e.g., "word ptr", "dword ptr", etc,
are not supported.  In many cases, you can just drop the "ptr" notation:

  ASM mov al,[esi]  ;use this
  ASM mov al,byte ptr[esi]  ;not this

In a pinch, one can use an assembler to compile a one-line program to get the
binary and do an insert like this:

=====test.asm
.586
.model flat, stdcall
option casemap :none

.code
xyz proc
fld tbyte ptr[ebx]   ;<<<<TEST STATEMENT
ret  ;marks end of statement with c3h in test.obj
xyz endp

end
=====test.asm

Compiling test.asm, in test.obj, at offset 64h, we see: DB 2B C3.
Therefore, our statement is DB 2B, or ASM db 0DBh,2Bh, or converting to
decimal:

  ASM dw 11227 ;fld tbyte ptr[ebx]


Copyright 2005-2007 James J Keene PhD
Original Publication: Nov 14, 2005
