Implemented calls using memory addresses
This commit is contained in:
parent
225d78e2d8
commit
acfa6de1d4
8 changed files with 114 additions and 10 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue