github.com/chenzhuoyu/iasm@v0.9.1/x86_64/assembler_test.go (about) 1 package x86_64 2 3 import ( 4 `fmt` 5 `os` 6 `os/exec` 7 `strings` 8 `testing` 9 10 `github.com/chenzhuoyu/iasm/obj` 11 `github.com/davecgh/go-spew/spew` 12 `github.com/stretchr/testify/require` 13 ) 14 15 func TestAssembler_Tokenizer(t *testing.T) { 16 k := new(_Tokenizer) 17 k.src = []rune(`movqorwhat $123, 123(%rax,%rbx), %rcx`) 18 for { 19 tk := k.next() 20 if tk.tag == _T_end { 21 break 22 } 23 spew.Dump(tk) 24 } 25 } 26 27 func TestAssembler_Parser(t *testing.T) { 28 p := new(Parser) 29 v, e := p.Feed("movq " + strings.Join([]string { 30 `$123`, 31 `$-123`, 32 `%rcx`, 33 `(%rax)`, 34 `123(%rax)`, 35 `-123(%rax)`, 36 `(%rax,%rbx,4)`, 37 `1234(%rax,%rbx,4)`, 38 `(,%rax,8)`, 39 `1234(,%rax,8)`, 40 `$(123 + 456)`, 41 `(123 + 456)(%rax)`, 42 `$'asd'`, 43 `$'asdf'`, 44 `$'asdfghj'`, 45 `$'asdfghjk'`, 46 }, ", ")) 47 require.NoError(t, e) 48 spew.Dump(v) 49 } 50 51 func TestAssembler_Assemble(t *testing.T) { 52 p := new(Assembler) 53 e := p.Assemble(` 54 .org 0x08000000 55 .entry start 56 57 msg: 58 .ascii "hello, world\n" 59 60 start: 61 movl $1, %edi 62 leaq msg(%rip), %rsi 63 movl $13, %edx 64 movl $0x02000004, %eax 65 syscall 66 xorl %edi, %edi 67 movl $0x02000001, %eax 68 syscall 69 `) 70 require.NoError(t, e) 71 code := p.Code() 72 base := p.Base() 73 entry := p.Entry() 74 spew.Dump(code) 75 fmt.Printf("Image Base : %#x\n", base) 76 fmt.Printf("Entry Point : %#x\n", entry) 77 fp, err := os.CreateTemp("", "macho_out-") 78 require.NoError(t, err) 79 err = obj.MachO.Write(fp, code, uint64(base), uint64(entry)) 80 require.NoError(t, err) 81 err = fp.Close() 82 require.NoError(t, err) 83 err = os.Chmod(fp.Name(), 0755) 84 require.NoError(t, err) 85 println("Saved to", fp.Name()) 86 out, err := exec.Command(fp.Name()).Output() 87 require.NoError(t, err) 88 spew.Dump(out) 89 require.Equal(t, []byte("hello, world\n"), out) 90 err = os.Remove(fp.Name()) 91 require.NoError(t, err) 92 } 93 94 func TestAssembler_RIPRelative(t *testing.T) { 95 p := new(Assembler) 96 e := p.Assemble(`leaq 0x1b(%rip), %rsi`) 97 require.NoError(t, e) 98 spew.Dump(p.Code()) 99 require.Equal(t, []byte { 0x48, 0x8d, 0x35, 0x1b, 0x00, 0x00, 0x00 }, p.Code()) 100 } 101 102 func TestAssembler_AbsoluteAddressing(t *testing.T) { 103 p := new(Assembler) 104 e := p.Assemble(` 105 movq 0x1234, %rbx 106 movq %rcx, 0x1234 107 `) 108 require.NoError(t, e) 109 spew.Dump(p.Code()) 110 require.Equal(t, []byte { 111 0x48, 0x8b, 0x1c, 0x25, 0x34, 0x12, 0x00, 0x00, 112 0x48, 0x89, 0x0c, 0x25, 0x34, 0x12, 0x00, 0x00, 113 }, p.Code()) 114 } 115 116 func TestAssembler_LockPrefix(t *testing.T) { 117 p := new(Assembler) 118 e := p.Assemble(`lock cmpxchgq %r9, (%rbx)`) 119 require.NoError(t, e) 120 spew.Dump(p.Code()) 121 require.Equal(t, []byte { 0xf0, 0x4c, 0x0f, 0xb1, 0x0b }, p.Code()) 122 } 123 124 func TestAssembler_SegmentOverride(t *testing.T) { 125 p := new(Assembler) 126 e := p.Assemble(` 127 movq gs:0x30, %rcx 128 movq gs:10(%rax), %rcx 129 movq fs:(%r9), %rcx 130 `) 131 require.NoError(t, e) 132 spew.Dump(p.Code()) 133 require.Equal(t, []byte { 134 0x65, 0x48, 0x8b, 0x0c, 0x25, 0x30, 0x00, 0x00, 0x00, 135 0x65, 0x48, 0x8b, 0x48, 0x0a, 136 0x64, 0x49, 0x8b, 0x09, 137 }, p.Code()) 138 }