22
33@(require (for-label (except-in racket compile)
44 a86))
5-
5+
66@(require scribble/examples
7- redex/reduction-semantics
7+ redex/reduction-semantics
88 redex/pict
99 (only-in pict scale)
1010 (only-in racket system)
@@ -67,7 +67,7 @@ int gcd(int n1, int n2) {
6767}
6868HERE
6969 )
70-
70+
7171 (parameterize ([current-directory (build-path notes "a86 " )])
7272 (save-file "tri.s " (asm-string (tri 36 )))
7373 (save-file "main.c " main.c)
@@ -178,7 +178,7 @@ Suppose we start executing at @tt{entry}.
178178 rbx} to zero. Executing this instruction sets a flag in the
179179 CPU, which affects subsequent ``conditional'' instructions.
180180 In this program, the next instruction is a conditional jump.}
181-
181+
182182 @item{@tt{je done} either jumps to the instruction
183183 following label @tt{done} or proceeds to the next
184184 instruction, based on the state of the comparison flag. The
@@ -192,7 +192,7 @@ Suppose we start executing at @tt{entry}.
192192 (register @tt{rsp}).}
193193
194194 @item{@tt{sub rbx, 1 } decrements @tt{rbx} by 1. }
195-
195+
196196 @item{@tt{call tri} performs something like a function
197197 call; it uses memory as a stack to save the current location
198198 in the code (which is where control should return to after
@@ -222,7 +222,7 @@ Suppose we start executing at @tt{entry}.
222222 ``output'') is 0. }
223223
224224 @item{@tt{ret} does a ``return,'' either to a prior call to
225- @tt{tri} or the caller of @tt{entry}.}
225+ @tt{tri} or the caller of @tt{entry}.}
226226 ]
227227
228228Despite the lower-level mechanisms, this code computes in a
@@ -535,7 +535,7 @@ save the result of @racket['f]:
535535(ex
536536(eg (seq (Call 'f )
537537 (Mov 'rbx 'rax )
538- (Call 'g )
538+ (Call 'g )
539539 (Add 'rax 'rbx )))
540540)
541541
@@ -634,13 +634,13 @@ address to jump to, we could've also written it as:
634634(ex
635635(eg (seq (Sub 'rsp 8 ) ; allocate a frame on the stack
636636 ; load address of 'fret label into top of stack
637- (Lea (Offset 'rsp 0 ) 'fret )
637+ (Lea (Offset 'rsp 0 ) 'fret )
638638 (Jmp 'f ) ; jump to 'f
639639 (Label 'fret ) ; <-- return point for "call" to 'f
640640 (Push 'rax ) ; save result (like before)
641641 (Sub 'rsp 8 ) ; allocate a frame on the stack
642642 ; load address of 'gret label into top of stack
643- (Lea (Offset 'rsp 0 ) 'gret )
643+ (Lea (Offset 'rsp 0 ) 'gret )
644644 (Jmp 'g ) ; jump to 'g
645645 (Label 'gret ) ; <-- return point for "call" to 'g
646646 (Pop 'rbx ) ; pop saved result from calling 'f
@@ -706,7 +706,7 @@ Each register plays the same role as in x86, so for example
706706 @tt{?}. The only characters which may be used as the first character of an
707707 identifier are letters, @tt{.} (with special meaning), @tt{_}
708708 and @tt{?}. "
709-
709+
710710 @ex[
711711 (label? 'foo )
712712 (label? "foo " )
@@ -796,6 +796,17 @@ Each register plays the same role as in x86, so for example
796796 ]
797797}
798798
799+ @defproc[(symbol->label [s symbol?]) label?]{
800+
801+ Returns a modified form of a symbol that follows NASM label conventions.
802+
803+ @ex[
804+ (let ([l (symbol->label 'my-great-label )])
805+ (seq (Label l)
806+ (Jmp l)))
807+ ]
808+ }
809+
799810@deftogether[(@defstruct*[% ([s string?])]
800811 @defstruct*[%% ([s string?])]
801812 @defstruct*[%%% ([s string?])])]{
@@ -820,7 +831,7 @@ Each register plays the same role as in x86, so for example
820831 (%% "we're done! " )
821832 (Ret))))
822833}
823-
834+
824835@defstruct*[Offset ([r register?] [i exact-integer?])]{
825836
826837 Creates an memory offset from a register. Offsets are used
@@ -865,7 +876,7 @@ Each register plays the same role as in x86, so for example
865876@defstruct*[Extern ([x label?])]{
866877
867878 Declares an external label.
868-
879+
869880}
870881
871882@defstruct*[Global ([x label?])]{
@@ -909,7 +920,7 @@ Each register plays the same role as in x86, so for example
909920}
910921
911922@defstruct*[Mov ([dst (or/c register? offset?)] [src (or/c register? offset? 64-bit-integer?)])]{
912-
923+
913924 A move instruction. Moves @racket[src] to @racket[dst].
914925
915926 Either @racket[dst] or @racket[src] may be offsets, but not both.
@@ -918,7 +929,7 @@ Each register plays the same role as in x86, so for example
918929 (asm-interp
919930 (prog
920931 (Global 'entry )
921- (Label 'entry )
932+ (Label 'entry )
922933 (Mov 'rbx 42 )
923934 (Mov 'rax 'rbx )
924935 (Ret)))
@@ -931,12 +942,12 @@ Each register plays the same role as in x86, so for example
931942
932943 An addition instruction. Adds @racket[src] to @racket[dst]
933944 and writes the result to @racket[dst].
934-
945+
935946 @ex[
936947 (asm-interp
937948 (prog
938949 (Global 'entry )
939- (Label 'entry )
950+ (Label 'entry )
940951 (Mov 'rax 32 )
941952 (Add 'rax 10 )
942953 (Ret)))
@@ -952,14 +963,14 @@ Each register plays the same role as in x86, so for example
952963 (asm-interp
953964 (prog
954965 (Global 'entry )
955- (Label 'entry )
966+ (Label 'entry )
956967 (Mov 'rax 32 )
957968 (Sub 'rax 10 )
958969 (Ret)))
959970 ]
960971}
961972
962- @defstruct*[Cmp ([a1 (or/c register? offset?)] [a2 (or/c register? offset? 32-bit-integer?)])]{
973+ @defstruct*[Cmp ([a1 (or/c register? offset?)] [a2 (or/c register? offset? 32-bit-integer?)])]{
963974 Compare @racket[a1] to @racket[a2]. Doing a comparison
964975 sets the status flags that affect the conditional instructions like @racket[Je], @racket[Jl], etc.
965976
@@ -972,14 +983,14 @@ Each register plays the same role as in x86, so for example
972983 (Cmp 'rax 2 )
973984 (Jg 'l1 )
974985 (Mov 'rax 0 )
975- (Label 'l1 )
986+ (Label 'l1 )
976987 (Ret)))
977- ]
988+ ]
978989}
979990
980991@defstruct*[Jmp ([x (or/c label? register?)])]{
981992 Jump to label @racket[x].
982-
993+
983994 @ex[
984995 (asm-interp
985996 (prog
@@ -996,15 +1007,15 @@ Each register plays the same role as in x86, so for example
9961007 (Global 'entry )
9971008 (Label 'entry )
9981009 (Mov 'rax 42 )
999- (Pop 'rbx )
1010+ (Pop 'rbx )
10001011 (Jmp 'rbx )))
10011012 ]
1002-
1013+
10031014}
10041015
10051016@defstruct*[Je ([x (or/c label? register?)])]{
10061017 Jump to label @racket[x] if the conditional flag is set to ``equal.''
1007-
1018+
10081019 @ex[
10091020 (asm-interp
10101021 (prog
@@ -1014,14 +1025,14 @@ Each register plays the same role as in x86, so for example
10141025 (Cmp 'rax 2 )
10151026 (Je 'l1 )
10161027 (Mov 'rax 0 )
1017- (Label 'l1 )
1028+ (Label 'l1 )
10181029 (Ret)))
10191030 ]
10201031}
10211032
10221033@defstruct*[Jne ([x (or/c label? register?)])]{
10231034 Jump to label @racket[x] if the conditional flag is set to ``not equal.''
1024-
1035+
10251036 @ex[
10261037 (asm-interp
10271038 (prog
@@ -1031,14 +1042,14 @@ Each register plays the same role as in x86, so for example
10311042 (Cmp 'rax 2 )
10321043 (Jne 'l1 )
10331044 (Mov 'rax 0 )
1034- (Label 'l1 )
1045+ (Label 'l1 )
10351046 (Ret)))
10361047 ]
10371048}
10381049
10391050@defstruct*[Jl ([x (or/c label? register?)])]{
10401051 Jump to label @racket[x] if the conditional flag is set to ``less than.''
1041-
1052+
10421053 @ex[
10431054 (asm-interp
10441055 (prog
@@ -1048,14 +1059,14 @@ Each register plays the same role as in x86, so for example
10481059 (Cmp 'rax 2 )
10491060 (Jl 'l1 )
10501061 (Mov 'rax 0 )
1051- (Label 'l1 )
1062+ (Label 'l1 )
10521063 (Ret)))
10531064 ]
10541065}
10551066
10561067@defstruct*[Jle ([x (or/c label? register?)])]{
10571068 Jump to label @racket[x] if the conditional flag is set to ``less than or equal.''
1058-
1069+
10591070 @ex[
10601071 (asm-interp
10611072 (prog
@@ -1065,14 +1076,14 @@ Each register plays the same role as in x86, so for example
10651076 (Cmp 'rax 42 )
10661077 (Jle 'l1 )
10671078 (Mov 'rax 0 )
1068- (Label 'l1 )
1079+ (Label 'l1 )
10691080 (Ret)))
10701081 ]
10711082}
10721083
10731084@defstruct*[Jg ([x (or/c label? register?)])]{
10741085 Jump to label @racket[x] if the conditional flag is set to ``greater than.''
1075-
1086+
10761087 @ex[
10771088 (asm-interp
10781089 (prog
@@ -1082,14 +1093,14 @@ Each register plays the same role as in x86, so for example
10821093 (Cmp 'rax 2 )
10831094 (Jg 'l1 )
10841095 (Mov 'rax 0 )
1085- (Label 'l1 )
1096+ (Label 'l1 )
10861097 (Ret)))
10871098 ]
10881099}
10891100
10901101@defstruct*[Jge ([x (or/c label? register?)])]{
10911102 Jump to label @racket[x] if the conditional flag is set to ``greater than or equal.''
1092-
1103+
10931104 @ex[
10941105 (asm-interp
10951106 (prog
@@ -1099,7 +1110,7 @@ Each register plays the same role as in x86, so for example
10991110 (Cmp 'rax 42 )
11001111 (Jg 'l1 )
11011112 (Mov 'rax 0 )
1102- (Label 'l1 )
1113+ (Label 'l1 )
11031114 (Ret)))
11041115 ]
11051116}
@@ -1523,13 +1534,13 @@ Each register plays the same role as in x86, so for example
15231534
15241535 Decrements the stack pointer and then stores the source
15251536 operand on the top of the stack.
1526-
1537+
15271538 @ex[
15281539 (asm-interp
15291540 (prog
15301541 (Global 'entry )
15311542 (Label 'entry )
1532- (Mov 'rax 42 )
1543+ (Mov 'rax 42 )
15331544 (Push 'rax )
15341545 (Mov 'rax 0 )
15351546 (Pop 'rax )
@@ -1539,13 +1550,13 @@ Each register plays the same role as in x86, so for example
15391550
15401551@defstruct*[Pop ([a1 register?])]{
15411552 Loads the value from the top of the stack to the destination operand and then increments the stack pointer.
1542-
1553+
15431554 @ex[
15441555 (asm-interp
15451556 (prog
15461557 (Global 'entry )
15471558 (Label 'entry )
1548- (Mov 'rax 42 )
1559+ (Mov 'rax 42 )
15491560 (Push 'rax )
15501561 (Mov 'rax 0 )
15511562 (Pop 'rax )
@@ -1569,7 +1580,7 @@ Perform bitwise not operation (each 1 is set to 0, and each 0 is set to 1) on th
15691580
15701581@defstruct*[Lea ([dst (or/c register? offset?)] [x label?])]{
15711582 Loads the address of the given label into @racket[dst].
1572-
1583+
15731584 @ex[
15741585 (asm-interp
15751586 (prog
@@ -1614,20 +1625,20 @@ Perform bitwise not operation (each 1 is set to 0, and each 0 is set to 1) on th
16141625 (Mov 'rax 42 )
16151626 (Ret)))
16161627 ]
1617-
1628+
16181629}
16191630
16201631@defproc[(asm-string [is (listof instruction?)]) string?]{
16211632
1622- Converts an a86 program to a string in nasm syntax.
1633+ Converts an a86 program to a string in nasm syntax.
16231634
16241635 @ex[
16251636 (asm-string (prog (Global 'entry )
16261637 (Label 'entry )
16271638 (Mov 'rax 42 )
16281639 (Ret)))
16291640 ]
1630-
1641+
16311642}
16321643
16331644@section{An Interpreter for a86}
@@ -1685,7 +1696,7 @@ The simplest form of interpreting an a86 program is to use
16851696 (Mov 'rax 0 )
16861697 (Jmp 'rax ))))
16871698 ]
1688-
1699+
16891700}
16901701
16911702It is often the case that we want our assembly programs to
@@ -1732,7 +1743,7 @@ code:
17321743 (Sub 'rsp 8 )
17331744 (Call 'gcd )
17341745 (Add 'rsp 8 )
1735- (Ret))))]
1746+ (Ret))))]
17361747
17371748This will be particularly relevant for writing a compiler
17381749where emitted code will make use of functionality defined in
@@ -1758,8 +1769,5 @@ linking error saying a symbol is undefined:
17581769
17591770 Like @racket[asm-interp], but uses @racket[in] for input and produce the result along
17601771 with any output as a string.
1761-
1762- }
1763-
1764-
17651772
1773+ }
0 commit comments