mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-21 01:56:47 +08:00
giant refactoring of macros
This commit is contained in:
parent
b153fad576
commit
4d41d9d9cd
5 changed files with 211 additions and 113 deletions
140
macros/README.md
140
macros/README.md
|
|
@ -25,15 +25,26 @@ underscores to labels defined by libraries such as the CRT and certain
|
|||
other symbols like `main`.
|
||||
|
||||
So, `main` will not be found by the linker on Apple systems and `_main`
|
||||
will be an error on Linux systems. There are macros to adjust for this.
|
||||
will be an error on Linux systems.
|
||||
|
||||
There are some exceptions such as making use of `FILE * stdin`. On
|
||||
Linux this would be `stdin`. On Mac OS you would expect `_stdin` but
|
||||
you'd be wrong... instead Apple uses `___stdinp`. Why? Apple.
|
||||
The macros adjust for this.
|
||||
|
||||
There are some exceptions to the prepending rule on Apple such as making
|
||||
use of `FILE * stdin`. On Linux this would be `stdin`. On Mac OS you
|
||||
would expect `_stdin` but you'd be wrong... instead Apple uses
|
||||
`___stdinp`. Why? Because Apple.
|
||||
|
||||
There is an assumption here that labels created by you do not have
|
||||
prepended underscores. This can be a problem if this isn't the case. The
|
||||
solution may be to add a parallel set of macros that either do prepend
|
||||
or do not. This is an open question which we hope to get user input to
|
||||
resolve.
|
||||
|
||||
## Macros of general use
|
||||
|
||||
These macros don't converge Apple and Linux. They're just nice to have.
|
||||
First, we describe a number of macros which are the same on both Apple
|
||||
and Linux. These macros don't converge Apple and Linux. They're just
|
||||
nice to have.
|
||||
|
||||
### PUSH_P, PUSH_R, POP_P and POP_R
|
||||
|
||||
|
|
@ -61,97 +72,114 @@ These resolve to: `.cfi_startproc` and `.cfi_endproc` respectively.
|
|||
|
||||
Handy more readable macros for determining minima and maxima.
|
||||
|
||||
`MIN x0, x1, x2`
|
||||
Signature:
|
||||
|
||||
resolves to:
|
||||
`MIN src_a, src_b, dest`
|
||||
|
||||
`csel x2, x0, x1, GT` putting the minimum of `x0` and `x1` into `x2`.
|
||||
The smaller of `src_a` and `src_b` is put into `dest`.
|
||||
|
||||
Signature:
|
||||
|
||||
`MAX src_a, src_b, dest`
|
||||
|
||||
The larger of `src_a` and `src_b` is put into `dest`.
|
||||
|
||||
## Loads and Stores
|
||||
|
||||
### GLD_PTR
|
||||
|
||||
Loads the address of a label and then dereferences it where, on Apple
|
||||
Loads the address of a label and then *dereferences* it where, on Apple
|
||||
the label is in the global space and on Linux is a relatively close
|
||||
label.
|
||||
|
||||
Apple version:
|
||||
Signature:
|
||||
|
||||
```text
|
||||
.macro GLD_PTR xreg, label // Dereference a global *
|
||||
adrp \xreg, _\label@GOTPAGE
|
||||
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
|
||||
.endm
|
||||
GLD_PTR xreg, label
|
||||
```
|
||||
|
||||
Linux version:
|
||||
When this macro finishes, the specified x register contains what
|
||||
64 bit value lives at the specified label.
|
||||
|
||||
### GLD_ADDR
|
||||
|
||||
Loads the address of the label into the specified x register. No
|
||||
dereferencing takes place. On Apple machines, the label will be
|
||||
found in the global space.
|
||||
|
||||
Signature:
|
||||
|
||||
```text
|
||||
.macro GLD_PTR xreg, label // Dereference a global *
|
||||
ldr \xreg, =\label
|
||||
ldr \xreg, [\xreg]
|
||||
.endm
|
||||
GLD_ADDR xreg, label
|
||||
```
|
||||
|
||||
When this macro completes, the address of the label is in the x
|
||||
register.
|
||||
|
||||
### LLD_ADDR
|
||||
|
||||
Load the value of a "local" label.
|
||||
Similar to `GLD_ADDR` this macro loads the address of a "local" label.
|
||||
|
||||
Apple version:
|
||||
Signature:
|
||||
|
||||
```text
|
||||
.macro LLD_ADDR xreg, label // Load a local address
|
||||
adrp \xreg, \label@PAGE
|
||||
add \xreg, \xreg, \label@PAGEOFF
|
||||
.endm
|
||||
LLD_ADDR xreg, label
|
||||
```
|
||||
|
||||
Linux version:
|
||||
When this macro completes, the address of the label is in the x
|
||||
register.
|
||||
|
||||
```text
|
||||
.macro LLD_ADDR xreg, label
|
||||
ldr \xreg, =\label
|
||||
.endm
|
||||
```
|
||||
### LLD_DBL
|
||||
|
||||
## Extern a global label
|
||||
Signature:
|
||||
|
||||
`LLD_DBL xreg, dreg, label`
|
||||
|
||||
When this macro completes, a double that lives at the specified local
|
||||
label will sit in the specified double register.
|
||||
|
||||
Note: No underscore is prepended.
|
||||
|
||||
See [this sample program](./double.S) for an example.
|
||||
|
||||
### LLD_FLT
|
||||
|
||||
Signature:
|
||||
|
||||
`LLD_FLT xreg, sreg, label`
|
||||
|
||||
When this macro completes, a float that lives at the specified
|
||||
local label will sit in the specified single precision
|
||||
register.
|
||||
|
||||
Note: No underscore is prepended.
|
||||
|
||||
See [this sample program](./float.S) for an example.
|
||||
|
||||
## Mark a label as global
|
||||
|
||||
Makes a label available externally.
|
||||
|
||||
Apple version:
|
||||
Signature:
|
||||
|
||||
```text
|
||||
.macro GLABEL label
|
||||
.global _\label
|
||||
.endm
|
||||
```
|
||||
`GLABEL label`
|
||||
|
||||
Linux version:
|
||||
An underscore is prepended.
|
||||
|
||||
```text
|
||||
.macro GLABEL label
|
||||
.global \label
|
||||
.endm
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```text
|
||||
GLABEL main
|
||||
```
|
||||
|
||||
## Calling functions
|
||||
## Calling CRT functions
|
||||
|
||||
If you create your own function without an underscore, just call it as
|
||||
usual.
|
||||
|
||||
If you need to call a function such as those found in the C runtime
|
||||
library, use in this way:
|
||||
library, use this macro in this way:
|
||||
|
||||
```text
|
||||
CRT strlen
|
||||
```
|
||||
`CRT strlen`
|
||||
|
||||
An underscore is prepended.
|
||||
|
||||
## Declaring `main()`
|
||||
|
||||
Put `MAIN` on a line by itself. Notice there is no colon.
|
||||
|
||||
An underscore is prepended.
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,77 +1,87 @@
|
|||
// Macros to permit the "same" assembly language to build on ARM64
|
||||
// Linux systems as well as Apple Silicon systems.
|
||||
//
|
||||
// Perry Kivolowitz
|
||||
// A Gentle Introduction to Assembly Language
|
||||
/* Macros to permit the "same" assembly language to build on ARM64
|
||||
Linux systems as well as Apple Silicon systems.
|
||||
|
||||
See the fuller documentation at:
|
||||
https://github.com/pkivolowitz/asm_book/blob/main/macros/README.md
|
||||
|
||||
Perry Kivolowitz
|
||||
A Gentle Introduction to Assembly Language
|
||||
*/
|
||||
|
||||
.macro GLD_PTR xreg, label
|
||||
#if defined(__APPLE__)
|
||||
|
||||
// Apple makes a distinction between loading something close by
|
||||
// versus something global. Note the use of GOTPAGE rather then
|
||||
// PAGE.
|
||||
//
|
||||
// Note: this macro dereferences the label getting what is at
|
||||
// the label's address.
|
||||
|
||||
.macro GLD_PTR xreg, label // Dereference a global *
|
||||
adrp \xreg, _\label@GOTPAGE
|
||||
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
|
||||
#else
|
||||
ldr \xreg, =\label
|
||||
ldr \xreg, [\xreg]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro GLD_ADDR xreg, label // Get a global address
|
||||
#if defined(__APPLE__)
|
||||
adrp \xreg, _\label@GOTPAGE
|
||||
add \xreg, \xreg, _\label@GOTPAGEOFF
|
||||
.endm
|
||||
|
||||
// This macro loads the address of a nearby label.
|
||||
|
||||
.macro LLD_ADDR xreg, label // Load a local address
|
||||
adrp \xreg, \label@PAGE
|
||||
add \xreg, \xreg, \label@PAGEOFF
|
||||
.endm
|
||||
|
||||
.macro GLABEL label
|
||||
.global _\label
|
||||
.endm
|
||||
|
||||
.macro MAIN
|
||||
_main:
|
||||
.endm
|
||||
|
||||
.macro CRT label
|
||||
bl _\label
|
||||
.endm
|
||||
|
||||
#else // LINUX
|
||||
|
||||
.macro GLABEL label
|
||||
.global \label
|
||||
.endm
|
||||
|
||||
.macro MAIN
|
||||
main:
|
||||
.endm
|
||||
|
||||
.macro CRT label
|
||||
bl \label
|
||||
.endm
|
||||
|
||||
// This macro treats label as a pointer and dereferences it.
|
||||
// That is, it puts into the xreg what is found at the address
|
||||
// of the label.
|
||||
|
||||
.macro GLD_PTR xreg, label // Dereference a global *
|
||||
#else
|
||||
ldr \xreg, =\label
|
||||
ldr \xreg, [\xreg]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
// This macro loads the address of a nearby label.
|
||||
|
||||
.macro LLD_ADDR xreg, label
|
||||
#if defined(__APPLE__)
|
||||
adrp \xreg, \label@PAGE
|
||||
add \xreg, \xreg, \label@PAGEOFF
|
||||
#else
|
||||
ldr \xreg, =\label
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro LLD_DBL xreg, dreg, label
|
||||
#if defined(__APPLE__)
|
||||
adrp \xreg, \label@PAGE
|
||||
add \xreg, \xreg, \label@PAGEOFF
|
||||
ldur \dreg, [\xreg]
|
||||
// fmov \dreg, \xreg
|
||||
#else
|
||||
ldr \xreg, =\label
|
||||
ldur \dreg, [\xreg]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro LLD_FLT xreg, sreg, label
|
||||
#if defined(__APPLE__)
|
||||
adrp \xreg, \label@PAGE
|
||||
add \xreg, \xreg, \label@PAGEOFF
|
||||
ldur \sreg, [\xreg]
|
||||
#else
|
||||
ldr \xreg, =\label
|
||||
ldur \sreg, [\xreg]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro GLABEL label
|
||||
#if defined(__APPLE__)
|
||||
.global _\label
|
||||
#else
|
||||
.global \label
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro MAIN
|
||||
#if defined(__APPLE__)
|
||||
_main:
|
||||
#else
|
||||
main:
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro CRT label
|
||||
#if defined(__APPLE__)
|
||||
bl _\label
|
||||
#else
|
||||
bl \label
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro START_PROC // after starting label
|
||||
.cfi_startproc
|
||||
|
|
|
|||
29
macros/double.S
Normal file
29
macros/double.S
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include "apple-linux-convergence.S"
|
||||
|
||||
.text
|
||||
.align 2
|
||||
GLABEL main
|
||||
|
||||
MAIN
|
||||
START_PROC
|
||||
PUSH_P x29, x30
|
||||
mov x29, sp
|
||||
LLD_ADDR x0, fmt
|
||||
LLD_DBL x1, d0, dbl
|
||||
#if defined(__APPLE__)
|
||||
PUSH_R d0
|
||||
CRT printf
|
||||
add sp, sp, 16
|
||||
#else
|
||||
CRT printf
|
||||
#endif
|
||||
POP_P x29, x30
|
||||
mov w0, wzr
|
||||
ret
|
||||
END_PROC
|
||||
|
||||
dbl: .double -0.55
|
||||
flt: .float 0.125
|
||||
fmt: .asciz "%f\n"
|
||||
|
||||
.end
|
||||
31
macros/float.S
Normal file
31
macros/float.S
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include "apple-linux-convergence.S"
|
||||
|
||||
.text
|
||||
.align 2
|
||||
GLABEL main
|
||||
|
||||
MAIN
|
||||
START_PROC
|
||||
PUSH_P x29, x30
|
||||
mov x29, sp
|
||||
LLD_ADDR x0, fmt
|
||||
LLD_FLT x1, s0, flt
|
||||
#if defined(__APPLE__)
|
||||
fcvt d0, s0
|
||||
fmov x1, d0
|
||||
PUSH_R x1
|
||||
CRT printf
|
||||
add sp, sp, 16
|
||||
#else
|
||||
fcvt d0, s0
|
||||
CRT printf
|
||||
#endif
|
||||
POP_P x29, x30
|
||||
mov w0, wzr
|
||||
ret
|
||||
END_PROC
|
||||
|
||||
flt: .float 0.125
|
||||
fmt: .asciz "%f\n"
|
||||
|
||||
.end
|
||||
Loading…
Reference in a new issue