mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-22 17:06:50 +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`.
|
other symbols like `main`.
|
||||||
|
|
||||||
So, `main` will not be found by the linker on Apple systems and `_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
|
The macros adjust for this.
|
||||||
Linux this would be `stdin`. On Mac OS you would expect `_stdin` but
|
|
||||||
you'd be wrong... instead Apple uses `___stdinp`. Why? Apple.
|
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
|
## 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
|
### 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.
|
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
|
## Loads and Stores
|
||||||
|
|
||||||
### GLD_PTR
|
### 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
|
the label is in the global space and on Linux is a relatively close
|
||||||
label.
|
label.
|
||||||
|
|
||||||
Apple version:
|
Signature:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.macro GLD_PTR xreg, label // Dereference a global *
|
GLD_PTR xreg, label
|
||||||
adrp \xreg, _\label@GOTPAGE
|
|
||||||
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
|
|
||||||
.endm
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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
|
```text
|
||||||
.macro GLD_PTR xreg, label // Dereference a global *
|
GLD_ADDR xreg, label
|
||||||
ldr \xreg, =\label
|
|
||||||
ldr \xreg, [\xreg]
|
|
||||||
.endm
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When this macro completes, the address of the label is in the x
|
||||||
|
register.
|
||||||
|
|
||||||
### LLD_ADDR
|
### 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
|
```text
|
||||||
.macro LLD_ADDR xreg, label // Load a local address
|
LLD_ADDR xreg, label
|
||||||
adrp \xreg, \label@PAGE
|
|
||||||
add \xreg, \xreg, \label@PAGEOFF
|
|
||||||
.endm
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Linux version:
|
When this macro completes, the address of the label is in the x
|
||||||
|
register.
|
||||||
|
|
||||||
```text
|
### LLD_DBL
|
||||||
.macro LLD_ADDR xreg, label
|
|
||||||
ldr \xreg, =\label
|
|
||||||
.endm
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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.
|
Makes a label available externally.
|
||||||
|
|
||||||
Apple version:
|
Signature:
|
||||||
|
|
||||||
```text
|
`GLABEL label`
|
||||||
.macro GLABEL label
|
|
||||||
.global _\label
|
|
||||||
.endm
|
|
||||||
```
|
|
||||||
|
|
||||||
Linux version:
|
An underscore is prepended.
|
||||||
|
|
||||||
```text
|
## Calling CRT functions
|
||||||
.macro GLABEL label
|
|
||||||
.global \label
|
|
||||||
.endm
|
|
||||||
```
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
GLABEL main
|
|
||||||
```
|
|
||||||
|
|
||||||
## Calling functions
|
|
||||||
|
|
||||||
If you create your own function without an underscore, just call it as
|
If you create your own function without an underscore, just call it as
|
||||||
usual.
|
usual.
|
||||||
|
|
||||||
If you need to call a function such as those found in the C runtime
|
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()`
|
## Declaring `main()`
|
||||||
|
|
||||||
Put `MAIN` on a line by itself. Notice there is no colon.
|
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
|
/* Macros to permit the "same" assembly language to build on ARM64
|
||||||
// Linux systems as well as Apple Silicon systems.
|
Linux systems as well as Apple Silicon systems.
|
||||||
//
|
|
||||||
// Perry Kivolowitz
|
|
||||||
// A Gentle Introduction to Assembly Language
|
|
||||||
|
|
||||||
|
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__)
|
#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
|
adrp \xreg, _\label@GOTPAGE
|
||||||
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
|
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
|
||||||
|
#else
|
||||||
|
ldr \xreg, =\label
|
||||||
|
ldr \xreg, [\xreg]
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro GLD_ADDR xreg, label // Get a global address
|
.macro GLD_ADDR xreg, label // Get a global address
|
||||||
|
#if defined(__APPLE__)
|
||||||
adrp \xreg, _\label@GOTPAGE
|
adrp \xreg, _\label@GOTPAGE
|
||||||
add \xreg, \xreg, _\label@GOTPAGEOFF
|
add \xreg, \xreg, _\label@GOTPAGEOFF
|
||||||
.endm
|
#else
|
||||||
|
|
||||||
// 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 *
|
|
||||||
ldr \xreg, =\label
|
ldr \xreg, =\label
|
||||||
ldr \xreg, [\xreg]
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
// This macro loads the address of a nearby label.
|
|
||||||
|
|
||||||
.macro LLD_ADDR xreg, label
|
.macro LLD_ADDR xreg, label
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
adrp \xreg, \label@PAGE
|
||||||
|
add \xreg, \xreg, \label@PAGEOFF
|
||||||
|
#else
|
||||||
ldr \xreg, =\label
|
ldr \xreg, =\label
|
||||||
|
#endif
|
||||||
.endm
|
.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
|
#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
|
.macro START_PROC // after starting label
|
||||||
.cfi_startproc
|
.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