TODO: Explain more in-depth
There are some key rules that have to be taken in account when coding for the 390, in short:
The name of sizes are different than in x86:
Writing assembly code is like putting bricks together, you can "construct" instructions like brasl, br, b, etc. It allows you to place "constructs" after the instruction, for example "R" "qualifier" tells the instruction to operate on registers, "HI" tells the instruction to operate on a halfword immediate, "I" tells the instruction to operate on a inmmediate, and so on.
GAS allows you to specify registers in any way you want:
# Pseudo-AT&T syntax larl %r14, myData # NASM-like larl r14, myData # Only number larl 14, myData
"Insert" means to place a value on the given register, some common instructions are:
Name | Operands | Full name | Description |
---|---|---|---|
BRASL | [register], [address] | Branch And Save Link |
Will save the current PC (after BRASL) in register, then branch into the specified address |
BR | [register] | Branch Register |
Will jump to the address contained in the register |
IPM | [register] | Insert Program Mask |
Will load the program mask into the given register, you can shift by 28 bits to obtain the CC flag |
SRL | [register], [immediate] | Shift Right Link |
Will shift register to the right by the amount specified by the immediate |
SLL | [register], [immediate] | Shift Left Link |
Same as above, but with the left side instead |
LARL | [register], [address] | Load Address into Register Link |
Will load the specified address into the specified register |
LHI | [register], [half-word immediate] | Loads a Half-word Immediate |
Loads the immediate into the specified register |
AHI | [register], [half-word immediate] | Add a Half-word Immediate |
Adds the immediate into the specified register |
SHI | [register], [half-word immediate] | Subtract a Half-word Immediate |
Subtract the immediate from the specified register |
OHI | [register], [half-word immediate] | ORs a Half-word Immediate |
ORs the immediate into the specified register |
NHI | [register], [half-word immediate] | ANDs a Half-word Immediate |
ANDs the immediate into the specified register |
C | [register], [register] | Compare |
Compares a register with another register |
BNE | [address] | Branch if Not Equal |
|
BNZ | [address] | Branch if Not Zero |
|
BZ | [address] | Branch if Zero |
|
BE | [address] | Branch if Equal |
Normally in S390 the assembly is done via HLASM, however most people prefer to use tools such as GAS. But sometimes you need to translate HLASM code to GAS
This is just a short description
Data Constant (abbreviated as DC) defines a constant which will be put in the final binary
* Insert a halfword DC X'00FF' * Insert a character DC X'0F'
Data S does not insert a constant into the final binary, however it is commonly used for alignment purpouses
* Pads to the half word boundary DS 0H * 2 uninitialized characters DS CL2
DS stands for Define Storage while DC stands for Define Character
HLASM uses macros too often, you'll see definitions like FLCIOA or FLCNPSW and such around HLASM code, those are part of macro libraries. However here is a small set of them defined in GAS syntax:
.equ AMBIT, 0x80000000 .equ FLCCAW, 0x48 .equ FLCSNPSW, 0x60 .equ FLCPNPSW, 0x68 .equ FLCINPSW, 0x78 .equ FLCMNPSW, 0x70 .equ FLCIOA, 0xB8
There are 2 states that may be useful to know, the problem state and the supervisor state. The problem state does not allow unprivileged execution of applications - this resembles usermode and can be used to "jail" rogue kernel modules. The supervisor state has full control over the machine and is usually where your kernel will run.
On x86 architectures the top of the stack is used as the initial RSP value, in S390 you use the bottom part of the stack instead.