Copy Link
Add to Bookmark
Report

xine-2.015

eZine's profile picture
Published in 
Xine
 · 26 Apr 2019

  


/-----------------------------\
| Xine - issue #2 - Phile 015 |
\-----------------------------/

General introduction to Amigas by Beol
--------------------------------------

In this doc I try to figure out the main differences between Amiga and
other computers. If someone is interested in Amiga hacking, he should
get a M680x0-Manual, the os-include files, and example sources.

CPU & Assembler
---------------

The Amiga uses the Motorolla 680x0 CPU family which is quite different
from the 80x86 family. I don't know much about the Intel-CPUs but
I'll try to point out the major differences:

* Real 32-bit cpu. (8bits are called byte, 16 bits word and 32 bits longword)

* 8 32-bit wide multiple-purpose data-registers (d0-d7). Unlike the 80x86
family, there is no instruction, wich forces you to use a special
data register (like mul on intel). You are allways free to use the
register you want.
Operations on dataregisters can usually have byte, word or longword
size. Byte and word operations only affect the least significant part
of the register. (Unlike intel al/ah)

* 8 32-bit wide address-registers. (a0-a7) These especially used for
addresscalculation, but good asm-hackers can abuse their properties
to produce smaller code.
Operations on address registers may have word or longword size, but
word-operators will ALLWAYS be sign extended to longword! So operations
will allways affect the whole addressregister.
Register a7 has a special meaning: it's the stackpointer. Some operations
(pea=push effective address or jsr=jump to subroutine will directly
affect a7 (I think this is called implicit addressing ?)). On the
other hand, you can use a7 just like every other addressregister.
(Infact there is no push or pop operation like on most other CPUs,
just use normal move operations!!)
Operations on address registers never change flags (this can be useful
for hackers!). Exception: cmp ea,ax and tst ax. (tst ax only available
on 68020+)

* Some other registers:
PC = Programmcounter (32 bit)
SR = Statusregister this is a 16 bit register split in to bytes:
the userbyte containing the usual flags (Carry,Overflow,Neg,
Zero and the X-Flag) and a systembyte containing information about
the processorstate (TraceMode,Supervisor-/User-mode,Interrupt mask).
The systembyte can only be accessed in supervisormode. Any attempt
to do so in user mode will create a privilege-fault exception.
Note that the X-Flag is something very special to the 680x0-family.
It's primary use is to do operations on operands bigger than 32 bits.
USP= User stack pointer. In usermode this is directly connected to a7.
In supervisor mode, you can use this to control the stack of a
user-programm. (Interesting for task-switching etc.)
SSP= Supervisor stack pointer. In supervisor mode this is connected to a7.
VBR= Vector Base Register. Only available on 68010+. This points to the
Exception-Vectors. On 68000 the Exception vectors allways start at
address 0. This register can only be accessed in supervisor mode.
If you want to patch exception vectors, you have to do this:
Check if processor is 68000 (ExecBase->AttnFlags). If yes, you can
directly patch the vector. If not you must go to supervisormode
(using a OS-function) get the VBR patch the vector and return to
usermode. (Note that you MUST return to usermode, because there
will be no task scheduling as long as you are in supervisormode!!
Never be in supervisor mode for a longer time!)
CACR=Cache control register. Not interesting, as this changes with every
processor and there are OS-routines for controling caches.
SFC,DFC=Only available on some processors and not interesting at all.

* No segmentation: No stupid segmentation like on intel. A 32bit address
just represents the bits that will be pushed on the address bus.
(Unless ofcourse the MMU is enabled).

* The format of an instruction is:
opcode[.size] src,dest
size is either .l for longwords .w for words and .b for bytes.
If the size is ommited, the default size is taken (.w for data
registers and .l for address registers (this is assembler-dependant!))
Some commands don't have a .size, because they only support one size
(e.g. pea) or they don't work on operands (e.g. nop).
Note that it's src,dest and not dest,src like on most other CPUs.

* Numeric constants:
12453 => decimal
$12ab => hex
%0110 => bin

* Addressing Modes:
There's a lot of addressing modes. The most important ones are:

Immediate: #constant (Normally 8,16, or 32 bit depending on command
Absolute: address.size
Dataregister direct: dx
Addressregister direct: ax (Only word and longword)
Addressregister indirect: (ax)
Addressregister indirect with postincrement: (ax)+ (nice for copying)
Addressregister indirect with predecrement: -(ax)
Addressregister indirect with addressdistance: ($xxxx,ax)
Addressregister indirect with index and addressdistance: ($xx,ax,Rx.s)
Rx=Address or data register .s=.W or .L
Programcounter relativ: ($xxxx,pc)
This one is very important for virusprogrammers as viruses have
to be pc-relativ. This is often used with labels. e.g.:

lea (NewLoadSeg,pc),a0 ;get address of our patch
move.l a0,(_LVOLoadSeg+2,a6) ;Patch library
[...]
LoadSeg: ;LoadSeg patch
[...]
rts
Programcounterrelativ with addressdistance: ($xx,PC,Rx.s)

The 68020+ CPUs feature some more Addressing Modes.
e.g.: move.w ([16,a0,d0.w*4],100),d0 Computes an address by
taking a0, adding 16 adding, 4*d0 (only the lower word), gets
the longword at this address, adds 100 to this longword, gets
the word at this new address and stores it in d0 (!!) On other
CPUs you would need 6 or more instructions to perform this!
You could even do:
move.w ([16,a0,d0.w*4],100),([40,a2,d1.l*8],4444) ;(!!!!!)


AmigaOS
-------

* The Amiga-OS differs completely from most other OSes: On one hand
it is a very modern OS (Preemptive Multitasking, Libraries, Devices,
Datatypes,...), on the other hand it totally lacks memory-protection
and recource tracking, making it the ideal OS for viruswriters.

* There is only one fixed address in the system: $00000004 contains the
address of the exec.library.


* The OS-functions are accessed by libraries. Before using the functions,
you have to open the library. (Exception: exec.library). The user can
add his own libraries to the system.
Calling a library function is easy: load the libraryaddress (or base)
to a6 (you MUST use a6!) and jump to the offset of the funtion.
e.g. to call dos.library/Output() you would do this:
move.l DOSBase(pc),a6 ;address of dos.library => a6
jsr _LVOOutput(a6) ;Call Output (LVO=Library Vector Offset)

All parameters for OS-libraries are passed over registers. No
OS-library-function gets parameters over stack!

All libraries follow the same register-conventions:
d0,d1,a0,a1 are scratchregisters and may be destroyed!
d2-d7,a2-a5 are preserved.
a6 must contain the librarybase and is preserved.
Only exception is dos.library, wich uses d2 and d3 as scratch too.


* devices are used for IO (e.g. keyboard.device, scsi.device, ...).
Unlike libraries, you don't call devices, but you send them
messages. Of course, before using devices you must open them (with
exec.library/OpenDevice()).

filehandlers are used for file operations. Programmers only use them
for two reasons: Async-IO and viruses. Otherwise you would use
dos.library functions.


* Multitasking makes virus writing much more interesting (in my opinion).
You can abuse the way the multitasking is implemented on Amiga, but
you allways have to make sure your virus is reentrant! This needs
some practice! Task switching can happen anytime anywhere (except
in interrupts, in supervisor mode or in Forbid()-mode), so manipulation
of shared data must be done very carefully!


dos.library
-----------

The dos part of the Amiga-OS was written in a great hurry and does not
fit at all to the rest. AmigaDOS is just _disgusting_! It was written
in BCPL. This has some drawbacks:
* BCPL-data must be aligned to 32-bit boundaries. So everytime
working with DOS, you MUST make sure that all structs are
longword-aligned!! This can lead to very subtle bugs, when
creating structures on stack...
* BCPL pointers (called BPTRs) point to the longword-address, not
to the byte-address!! So when having a BPTR, you must shift it
2 bits to the left!
To make the situation even more confusing, dos uses sometimes
BPTRs and sometimes normal C-style pointers!!!!
* BCPL strings are like pascal-strings: 1st byte=length, rest=data.
Same problem: dos mixes C-style and BCPL-style strings!!!
(When an include says BSTR, this is a BCPL-pointer to a BCPL-string)

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT