Implemented calls using memory addresses

This commit is contained in:
Eduard Urbach 2025-03-03 00:53:41 +01:00
parent 225d78e2d8
commit acfa6de1d4
Signed by: eduard
GPG key ID: 49226B848C78F6C8
8 changed files with 114 additions and 10 deletions

View file

@ -34,9 +34,9 @@ func CallRegister(code []byte, register cpu.Register) []byte {
)
}
// CallAtAddress calls a function at the address stored at the given memory address.
// CallAt calls a function at the address stored at the given memory address.
// The memory address is relative to the next instruction.
func CallAtAddress(code []byte, address uint32) []byte {
func CallAt(code []byte, address uint32) []byte {
return append(
code,
0xFF,
@ -47,3 +47,33 @@ func CallAtAddress(code []byte, address uint32) []byte {
byte(address>>24),
)
}
// CallAtMemory calls a function at the address stored at the given memory address.
// The memory address is relative to the next instruction.
func CallAtMemory(code []byte, register cpu.Register, offset int8) []byte {
mod := AddressMemory
if offset != 0 || register == RBP || register == R13 {
mod = AddressMemoryOffset8
}
reg := byte(0b010)
rm := register
if rm > 0b111 {
code = append(code, 0x41)
rm &= 0b111
}
code = append(code, 0xFF, ModRM(mod, reg, byte(rm)))
if register == RSP || register == R12 {
code = append(code, SIB(Scale1, 0b100, 0b100))
}
if mod == AddressMemoryOffset8 {
code = append(code, byte(offset))
}
return code
}

View file

@ -37,3 +37,51 @@ func TestCallRegister(t *testing.T) {
assert.DeepEqual(t, code, pattern.Code)
}
}
func TestCallAtMemory(t *testing.T) {
usagePatterns := []struct {
Register cpu.Register
Offset int8
Code []byte
}{
{x86.RAX, 0, []byte{0xFF, 0x10}},
{x86.RCX, 0, []byte{0xFF, 0x11}},
{x86.RDX, 0, []byte{0xFF, 0x12}},
{x86.RBX, 0, []byte{0xFF, 0x13}},
{x86.RSP, 0, []byte{0xFF, 0x14, 0x24}},
{x86.RBP, 0, []byte{0xFF, 0x55, 0x00}},
{x86.RSI, 0, []byte{0xFF, 0x16}},
{x86.RDI, 0, []byte{0xFF, 0x17}},
{x86.R8, 0, []byte{0x41, 0xFF, 0x10}},
{x86.R9, 0, []byte{0x41, 0xFF, 0x11}},
{x86.R10, 0, []byte{0x41, 0xFF, 0x12}},
{x86.R11, 0, []byte{0x41, 0xFF, 0x13}},
{x86.R12, 0, []byte{0x41, 0xFF, 0x14, 0x24}},
{x86.R13, 0, []byte{0x41, 0xFF, 0x55, 0x00}},
{x86.R14, 0, []byte{0x41, 0xFF, 0x16}},
{x86.R15, 0, []byte{0x41, 0xFF, 0x17}},
{x86.RAX, 1, []byte{0xFF, 0x50, 0x01}},
{x86.RCX, 1, []byte{0xFF, 0x51, 0x01}},
{x86.RDX, 1, []byte{0xFF, 0x52, 0x01}},
{x86.RBX, 1, []byte{0xFF, 0x53, 0x01}},
{x86.RSP, 1, []byte{0xFF, 0x54, 0x24, 0x01}},
{x86.RBP, 1, []byte{0xFF, 0x55, 0x01}},
{x86.RSI, 1, []byte{0xFF, 0x56, 0x01}},
{x86.RDI, 1, []byte{0xFF, 0x57, 0x01}},
{x86.R8, 1, []byte{0x41, 0xFF, 0x50, 0x01}},
{x86.R9, 1, []byte{0x41, 0xFF, 0x51, 0x01}},
{x86.R10, 1, []byte{0x41, 0xFF, 0x52, 0x01}},
{x86.R11, 1, []byte{0x41, 0xFF, 0x53, 0x01}},
{x86.R12, 1, []byte{0x41, 0xFF, 0x54, 0x24, 0x01}},
{x86.R13, 1, []byte{0x41, 0xFF, 0x55, 0x01}},
{x86.R14, 1, []byte{0x41, 0xFF, 0x56, 0x01}},
{x86.R15, 1, []byte{0x41, 0xFF, 0x57, 0x01}},
}
for _, pattern := range usagePatterns {
t.Logf("call [%s+%d]", pattern.Register, pattern.Offset)
code := x86.CallAtMemory(nil, pattern.Register, pattern.Offset)
assert.DeepEqual(t, code, pattern.Code)
}
}

View file

@ -9,7 +9,7 @@ import (
func TestX86(t *testing.T) {
assert.DeepEqual(t, x86.Call(nil, 1), []byte{0xE8, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x86.CallAtAddress(nil, 1), []byte{0xFF, 0x15, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x86.CallAt(nil, 1), []byte{0xFF, 0x15, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x86.ExtendRAXToRDX(nil), []byte{0x48, 0x99})
assert.DeepEqual(t, x86.MoveRegisterNumber(nil, 0, 1), []byte{0xB8, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x86.MoveRegisterNumber(nil, 1, 1), []byte{0xB9, 0x01, 0x00, 0x00, 0x00})