Here is another one from Carl that I found on the newsgroups:
Carl W. Sumner [email protected]
Re: Assembler in Clarion
The c compiler syntax is very standard. Any book on C will do. No header files though.
The assembler is harder but to get the op codes I just opened the assembler exe in the bin subdir in a hex editor and they jumped out at me.
Here are the notes I have built and collected over the years.
Note:
These directives are equivalents of a #ifdef _WIN32 / #endif
. The reason for the data segment was actually the result of a copy and paste from some other larger body of code.
module AsmSupport
%T - ifdef - true
%F - ifndef - false
%E - endif
(* Segment Attributes *)
use16 = 00H
use32 = 01H
abs_align = 00H
byte_align = 20H
word_align = 40H
para_align = 60H
page_align = 80H
dword_align = 0A0H
dont_combine = 00H
memory_combine = 04H
public_combine = 08H
stack_combine = 14H
common_combine = 18H
(* %T _WIN32 *)
segment _DATA(DATA, use32 + dword_align + public_combine)
segment _TEXT(CODE, use32 + dword_align + public_combine)
select _TEXT
section
public _DynPolygon :
extrn Cla$POLYGON
call Cla$POLYGON
ret 0
(* %E *)
end
module Call
(* Segment Attributes *)
use16 = 00H
use32 = 01H
abs_align = 00H
byte_align = 20H
word_align = 40H
para_align = 60H
page_align = 80H
dword_align = 0A0H
dont_combine = 00H
memory_combine = 04H
public_combine = 08H
stack_combine = 14H
common_combine = 18H
(* %T _WIN32 *)
segment _DATA(DATA, use32 + dword_align + public_combine)
segment _TEXT(CODE, use32 + dword_align + public_combine)
select _TEXT
section
public _DebugBreak :
db 204
ret 0
(* %E *)
end
(1) Changes/incompatibilities
Some memory operands need to be given an explicit type where none was
needed previously, e.g.
push word [bp][-6]
pop word [bp][-6]
Some floating point instructions need to have the specifier moved to just in front of the memory operand, e.g.
fld st(0), qword [si]
rather than
fld qword st(0), [si]
There are many new opcodes. All opcodes are now reserved and cannot be used as labels e.g.
loop = 2 (loop instruction)
str = -6 (store task register instruction)
....
(3) New Features
Out of range jumps are automatically corrected, using 386 jump opcodes or extra jumps where necessary.
All 8086/8087 … 386/387/486 opcodes are supported. The correct segment override, data and address prefixes are automatically generated.
The size of operands is specified using byte/word/dword/fword/qword/tbyte/ptr/near/far.
fword means 48-bits, made up of a 16-bit segment + 32-bit offset.
ptr means a 16-bit segment + 16-bit offset.
dword means a 32-bit offset.
near means a word or dword depending on whether the current segment
is 16 or 32 bit.
far means ptr or fword depending on whether the current segment
is 16 or 32 bit.
e.g.
call near xxx
call near [edi]
and dword [di], 1
fstp st(0), qword [esp]
call ptr far_proc_in_16_bit_seg
call fword far_proc_in_32_bit_seg
32-bit segments are specified by the least significant bit of the segment attribute. Equates suitable for specifying segment attributes are as follows:
(* segment attributes *)
use16 = 0H
use32 = 1H
abs_align = 00H
byte_align = 20H
word_align = 40H
para_align = 60H
page_align = 80H
dword_align = 0A0H
dont_combine = 00H
memory_combine = 04H
public_combine = 08H
stack_combine = 14H
common_combine = 18H
A typical usage is then
segment _TEXT('CODE',use16+byte_align+public_combine)
Equated symbols may now be given any expression which can be used as an operand for an instruction, rather than just a numeric constant.
For example:
v6 = word [bp][-6]
...
mov ax, v6
Simple (parameter-less) macros can be defined.
For example:
macro movsb "movs byte [si], byte es:[di]"
Note that no processing is performed during macro definition except to look for the delimiter. In particular there is no conditional processing or macro expansion. The delimiter may any non-blank character and may be repeated. The delimiter(s) are removed when the macro is invoked.
A symbol can be purged (deleted) from the symbol table using purge fred
(4) The reserved words are as follows:
byte
word
dword
fword
qword
tbyte
db
dw
dd
df
log2
power2
ptr
seg
vdisp
far
near
end
extrn
group
include
macro
module
org
public
purge
section
segment
select
st
The register names are:
es cs ss ds fs gs
ax cx dx bx sp bp si di
eax ecx edx ebx esp ebp esi edi
al cl dl bl ah ch dh bh
cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7
dr0 dr1 dr2 dr3 dr4 dr5 dr6 dr7
tr0 tr1 tr2 tr3 tr4 tr5 tr6 tr7
st(0) st(1) st(2) st(3) st(4) st(5) st(6) st(7)
The opcode names (also reserved) are:
aaa aad aam aas adc add and arpl
bound bsf bsr bswap bt btc btr bts
call clc cld cli clts cmc cmp cmps
cmpxchg daa das dec div enter esc halt
idiv imul in inc ins int into invd
invlpg jmp
jb jae je jne jbe ja jp jpo
jl jge jle jg jo jno js jns
lahf lar lds lea leave les lfs lgdt
lgs lidt lldt lmsw lods
lsl lss ltr mov movs movsx movzx mul
neg nop not or out outs pop push
rcl rcr rol ror sahf sar sbb scas
retf retn
setb setae sete setne setbe seta setp setpo
setl setge setle setg seto setno sets setns
sgdt shl shld shr shrd
sidt sldt smsw stc std sti stos str
sub test verr verw wbinvd fwait xadd xchg
xlats xor
f2xm1 fabs fadd faddp fbld fbstp fchs fclex
fcom fcomp fcompp fdecstpfdiv fdivp fdivr fdivrp
ffree fiadd ficom ficomp fidiv fidivr fild fimul
fincstp finit fist fistp fisub fisubr fld fld1
fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz
fmul fmulp fnop fpatan fprem fptan frndint frstor
fsave fscale fsetpm fsqrt fst fstcw fstenv fstp
fstsw fsub fsubp fsubr fsubrp ftst fxam fxch
fxtract fyl2x fyl2xp1 fsin fcos fsincos fprem1 fucom
fucomp fucompp fdisi feni
lock rep repne
cbw cwd iret pusha pushf popa popf
jcxz loop loope loopne
cwde cdq iretd pushad pushfd popad popfd
jecxz loopd looped loopned
ret
(5) Things to watch out for:
The meaning of an instruction is derived from the opcode or operands, and prefixes are generated as necessary e.g.
cwde
cdq
iretd
jecxz lab
loopd lab
pushad
pushfd
popad
popfd
push dword 0
push dword [si]
Note that loop/loope/loopne always means “loop on cx”. To loop on ecx
loopd/looped/loopned
must be used. (This is not the same as Microsoft where the meaning of loop depends on the whether the current segment is 32-bit)
However the the default size of the offset of a label depends on whether the current segment is 16-bit or 32-bit.
extrn fred
inc byte es:[fred]
The offset size can be specified explicitly, e.g.
extrn fred
inc byte es:[dword fred] (* 32-bit offset *)
inc byte es:[word fred] (* 16-bit offset *)
(6) The assembler requires string instructions to have operands.
The old short forms may be expressed as macros:
macro lodsb "lods byte [si]"
macro lodsw "lods word [si]"
macro stosb "stos byte es:[di]"
macro stosw "stos word es:[di]"
macro scasb "scas byte es:[di]"
macro scasw "scas word es:[di]"
macro movsb "movs byte [si], byte es:[di]"
macro movsw "movs word [si], word es:[di]"
macro cmpsb "cmps byte [si], byte es:[di]"
macro cmpsw "cmps word [si], word es:[di]"
macro xlat "xlats byte [bx]"
However for readability I suggest using the long forms.
32-bit addressing is achieved by using esi/edi.
The source segment may be over-ridden, e.g.
e.g. lodsb byte ss:[si] )
Beware of doing this in conjunction with rep on 8086’s since on an interrupt multiple prefixes are not saved.
Other opcodes which are defined as macros are as follows:
macro repe "rep"
macro repz "rep"
macro repnz "repne"
macro jc "jb"
macro jnc "jnb"
macro jnae "jb"
macro jnb "jae"
macro jz "je"
macro jnz "jne"
macro jna "jbe"
macro jnbe "ja"
macro jpe "jp"
macro jnp "jpo"
macro jnge "jl"
macro jnl "jge"
macro jng "jle"
macro jnle "jg"
macro setnae "setb"
macro setnb "setae"
macro setz "sete"
macro setnz "setne"
macro setna "setbe"
macro setnbe "seta"
macro setpe "setp"
macro setnp "setpo"
macro setnge "setl"
macro setnl "setge"
macro setng "setle"
macro setnle "setg"