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 }
139
View as plain text