-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAssembly.hs
137 lines (116 loc) · 3.42 KB
/
Assembly.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
{-# LANGUAGE DeriveGeneric, DeriveAnyClass, DeriveDataTypeable, BangPatterns #-}
module Language.X86.Assembly where
import Data.Foldable (foldl')
import Data.Data
import GHC.Generics
import Control.DeepSeq
import Data.Int (Int32)
import Data.Maybe (mapMaybe)
import qualified Data.Sequence as S
import qualified Data.Map as M
import qualified Data.Set as Set
data Code = Code
{ cCode :: S.Seq Line
, cLabelMap :: M.Map Label Int32
, cLabelMapOrig :: M.Map Label Int32
, cBreakpoints :: Set.Set Int32
}
deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, NFData)
data Line = Line
{ lineAnn :: !Int32
, lineInst :: !Instruction
}
deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, NFData)
-- | The Instruction type
-- represents an x86 assembly instruction
data Instruction
= IMov !Arg !Arg
| IAdd !Arg !Arg
| ISub !Arg !Arg
| ICmp !Arg !Arg
| IXor !Arg !Arg
| IAnd !Arg !Arg
| IOr !Arg !Arg
| IShl !Arg !Arg
| IShr !Arg !Arg
| ISar !Arg !Arg
| ISal !Arg !Arg
| ITest !Arg !Arg
| IMul !Arg
| Label !Label
| IJmp !Address
| IJe !Address
| IJne !Address
| IJnz !Address
| IJz !Address
| IJge !Address
| ICall !Address
| IPush !Arg
| IPop !Arg
| IRet
| IHalt
deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, NFData)
type Label = String
data AddressVar
= AL Label
| AR Reg
deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, NFData)
type Address = ArithExpr AddressVar
-- | The Arg type
-- represents an x86 assembly argument to an instruction
data Arg
= Ref !Arg
| AE !(ArithExpr Reg)
| AEL !Address
deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, NFData)
data ArithExpr var
= Lit !Int32
| Var !var
| Add !(ArithExpr var) !(ArithExpr var)
| Mul !(ArithExpr var) !(ArithExpr var)
| Sub !(ArithExpr var) !(ArithExpr var)
deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, NFData)
-- | The Reg type
-- represents an x86 assembly register
data Reg
= EAX
| EBX
| ECX
| EDX
| ESP
| EBP
| ESI
| EIP
deriving (Show, Read, Eq, Ord, Generic, NFData, Data, Typeable, Bounded, Enum)
-- | x86 flags
-- Description taken from: http://unixwiz.net/techtips/x86-jumps.html
data Flag
= CF -- ^ carry flag: Set on high-order bit carry or borrow; cleared otherwise
| ZF -- ^ zero flags: Set if result is zero; cleared otherwise
| SF -- ^ sign flag: Set equal to high-order bit of result (0 if positive 1 if negative)
| OF -- ^ overflow flag: Set if result is too large a positive number or too small a negative number (excluding sign bit) to fit in destination operand; cleared otherwise
-- | PF -- ^ parity flag: Set if low-order eight bits of result contain an even number of "1" bits; cleared otherwise
deriving (Show, Read, Eq, Ord, Generic, NFData, Data, Typeable)
data Loc
= LocReg Reg
| LocMem Int32
deriving (Show, Read, Eq, Ord, Generic, NFData, Data, Typeable)
toCode :: [Label] -> [Instruction] -> Code
toCode breaks insts = Code
{ cCode =
S.fromList
. reverse
. (Line lastNum IHalt:)
$ rInstructions
, cLabelMap = labelmap
, cLabelMapOrig = labelmap
, cBreakpoints = Set.fromList $
mapMaybe (`M.lookup` labelmap) breaks
}
where
(labelmap, rInstructions, lastNum) = foldl' go (M.empty, [], 0) insts
go (labels, rLines, num) = \case
Label l ->
(M.insert l num labels, rLines, num)
inst ->
(labels, Line num inst : rLines, num + 1)