about summary refs log tree commit diff stats
path: root/archive/2.transect/compiler9
blob: 26becf48a8b12fcf4099f29c438d7305e3b9297c (plain) (blame)
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
=== Goal

A memory-safe language with a simple translator to x86 that can be feasibly
written without itself needing a translator.

Memory-safe: it should be impossible to:
  a) create a pointer out of arbitrary data, or
  b) to access heap memory after it's been freed.

Simple: do all the work in a 2-pass translator:
  Pass 1: check each instruction's types in isolation.
  Pass 2: emit code for each instruction in isolation.

=== Overview of the language

A program consists of a series of type, function and global variable declarations.
(Also constants and tests, but let's focus on these.)

Type declarations basically follow Hindley-Milner with product and (tagged) sum
types. Types are written in s-expression form. There's a `ref` type that's a
type-safe fat pointer, with an alloc id that gets incremented after each
allocation. Memory allocation and reclamation is manual. Dereferencing a ref
after its underlying memory is reclaimed (pointer alloc id no longer matches
payload alloc id) is guaranteed to immediately kill the program (like a
segfault).

  # product type
  type foo [
    x : int
    y : (ref int)
    z : bar
  ]

  # sum type
  choice bar [
    x : int
    y : point
  ]

Functions have a header and a series of instructions in the body:

  fn f a : int -> b : int [
    ...
  ]

Instructions have the following format:

  io1, io2, ... <- operation i1, i2, ...

i1, i2 operands on the right hand side are immutable. io1, io2 are in-out
operands. They're written to, and may also be read.

User-defined functions will be called with the same syntax. They'll translate
to a sequence of push instructions (one per operand, both in and in-out), a
call instruction, and a sequence of pop instructions, either to a black hole
(in operands) or a location (in-out operands). This follows the standard Unix
calling convention. Each operand needs to be something push/pop can accept.

Primitive operations depend on the underlying processor. We'd like each primitive
operation supported by the language to map to a single instruction in the ISA.
Sometimes we have to violate that (see below), but we definitely won't be
writing to any temporary locations behind the scenes. The language affords
control over registers, and tracking unused registers gets complex, and
besides we may have no unused registers at a specific point. Instructions only
modify their operands.

In most ISAs, instructions operate on at most a word of data at a time. They
also tend to not have more than 2-3 operands, and not modify more than 2
locations in memory.

Since the number of reads from memory is limited, we break up complex high-level
operations using a special type called `address`. Addresses are strictly
short-term entities. They can't be stored in a compound type, and they can't
be passed into or returned from a user-defined function. They also can't be
used after a function call (because it could free the underlying memory) or
label (because it gets complex to check control flow, and we want to translate
each instruction simply and in isolation).

=== Compilation to 32-bit x86

Values can be stored:
  in code (literals)
  in registers
  on the stack
  on the global segment

Variables on the stack are stored at *(ESP+n)
Global variables are stored at *disp32, where disp32 is statically known

Address variables have to be in a register.
  - You need them in a register to do a lookup, and
  - Saving them to even the stack increases the complexity of checks needed on
    function calls or labels.

Compilation proceeds by pattern matching over an instruction along with
knowledge about the types of its operands, as well as where they're stored
(register/stack/global). We now enumerate mappings for various categories of
instructions, based on the type and location of their operands.

Where types of operands aren't mentioned below, all operands of an instruction
should have the same (word-length) type.

Lots of special cases because of limitations of the x86 ISA. Beware.

A. x : int <- add y

  Requires y to be scalar. Result will always be an int. No pointer arithmetic.

  reg <- add literal    => 81 0/subop 3/mod                                                                                           ...(0)
  reg <- add reg        => 01 3/mod                                                                                                   ...(1)
  reg <- add stack      => 03 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8 reg/r32                                        ...(2)
  reg <- add global     => 03 0/mod 5/rm32/include-disp32 global/disp32 reg/r32                                                       ...(3)
  stack <- add literal  => 81 0/subop 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8 literal/imm32                          ...(4)
  stack <- add reg      => 01 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8 reg/r32                                        ...(5)
  stack <- add stack    => disallowed
  stack <- add global   => disallowed
  global <- add literal => 81 0/subop 0/mod 5/rm32/include-disp32 global/disp32 literal/imm32                                         ...(6)
  global <- add reg     => 01 0/mod 5/rm32/include-disp32 global/disp32 reg/r32                                                       ...(7)
  global <- add stack   => disallowed
  global <- add global  => disallowed

Similarly for sub, and, or, xor and even copy. Replace the opcodes above with corresponding ones from this table:

                            add             sub           and           or            xor         copy/mov
  reg <- op literal         81 0/subop      81 5/subop    81 4/subop    81 1/subop    81 6/subop  c7
  reg <- op reg             01 or 03        29 or 2b      21 or 23      09 or 0b      31 or 33    89 or 8b
  reg <- op stack           03              2b            23            0b            33          8b
  reg <- op global          03              2b            23            0b            33          8b
  stack <- op literal       81 0/subop      81 5/subop    81 4/subop    81 1/subop    81 6/subop  c7
  stack <- op reg           01              29            21            09            31          89
  global <- op literal      81 0/subop      81 5/subop    81 4/subop    81 1/subop    81 6/subop  c7
  global <- op reg          01              29            21            09            31          89

B. x/reg : int <- mul y

  Requires both y to be scalar.
  x must be in a register. Multiplies can't write to memory.

  reg <- mul literal    => 69                                                                                                         ...(8)
  reg <- mul reg        => 0f af 3/mod                                                                                                ...(9)
  reg <- mul stack      => 0f af 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8 reg/r32                                     ...(10)
  reg <- mul global     => 0f af 0/mod 5/rm32/include-disp32 global/disp32 reg/r32                                                    ...(11)

C. x/EAX/quotient : int, y/EDX/remainder : int <- idiv z     # divide EAX by z; store the result in EAX and EDX

  Requires source x and z to both be scalar.
  x must be in EAX and y must be in EDX. Divides can't write anywhere else.

  First clear EDX (we don't support ints larger than 32 bits):
  31/xor 3/mod 2/rm32/EDX 2/r32/EDX

  then:
  EAX, EDX <- idiv literal  => disallowed
  EAX, EDX <- idiv reg      => f7 7/subop 3/mod                                                                                       ...(12)
  EAX, EDX <- idiv stack    => f7 7/subop 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8                                    ...(13)
  EAX, EDX <- idiv global   => f7 7/subop 0/mod 5/rm32/include-disp32 global/disp32 reg/r32                                           ...(14)

D. x : int <- not

  Requires x to be an int.

  reg <- not                => f7 3/mod                                                                                               ...(15)
  stack <- not              => f7 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8                                            ...(16)
  global <- not             => f7 0/mod 5/rm32/include-disp32 global/disp32 reg/r32                                                   ...(17)

E. x : (address t) <- get o : T, %f

  (Assumes T.f has type t.)

  o can't be on a register since it's a non-primitive (likely larger than a word)
  f is a literal
  x must be in a register (by definition for an address)

  below '*' works on either address or ref types

  For raw stack values we want to read *(ESP+n)
  For raw global values we want to read *disp32
  For address stack values we want to read *(ESP+n)+
    *(ESP+n) contains an address
    so we want to compute *(ESP+n) + literal

  reg1 <- get reg2, literal       => 8d/lea 1/mod reg2/rm32 literal/disp8 reg1/r32                                                    ...(18)
  reg <- get stack, literal       => 8d/lea 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n+literal/disp8 reg/r32                  ...(19)
    (simplifying assumption: stack frames can't be larger than 256 bytes)
  reg <- get global, literal      => 8d/lea 0/mod 5/rm32/include-disp32 global+literal/disp32, reg/r32                                ...(20)

F. x : (offset T) <- index i : int, %size(T)

  reg1 <- index reg2, literal       => 69/mul 3/mod reg2/rm32 literal/imm32 -> reg1/r32
                                    or 68/mul 3/mod reg2/rm32 literal/imm8 -> reg1/r32                                                ...(21)
  reg1 <- index stack, literal      => 69/mul 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n/disp8 literal/imm32 -> reg1/r32      ...(22)
  reg1 <- index global, literal     => 69/mul 0/mod 5/rm32/include-disp32 global/disp32 literal/imm32 -> reg1/r32                     ...(23)

  optimization: avoid multiply if literal is a power of 2
    use SIB byte if literal is 2, 4 or 8
    or left shift

G. x : (address T) <- advance o : (array T), idx : (offset T)

  reg <- advance a/reg, idx/reg   => 8d/lea 0/mod 4/rm32/SIB a/base idx/index 0/scale reg/r32                                         ...(24)
  reg <- advance stack, literal   => 8d/lea 1/mod 4/rm32/SIB 4/base/ESP 4/index/none 0/scale n+literal/disp8 reg/r32                  ...(25)
  reg <- advance stack, reg2      => 8d/lea 1/mod 4/rm32/SIB 4/base/ESP reg2/index 0/scale n/disp8 reg/r32                            ...(26)
  reg <- advance global, literal  => 8d/lea 0/mod 5/rm32/include-disp32 global+literal/disp32, reg/r32                                ...(27)

  also instructions for runtime bounds checking

=== Example

Putting it all together: code generation for `a[i].y = 4` where a is an array
of 2-d points with x, y coordinates.

If a is allocated on the stack, say of type (array point 6) at (ESP+4):

  offset/EAX : (offset point) <- index i, 8  # (22)
  tmp/EBX : (address point) <- advance a : (array point 6), offset/EAX  # (26)
  tmp2/ECX : (address number) <- get tmp/EBX : (address point), 4/y  # (18)
  *tmp2/ECX <- copy 4  # (5 for copy/mov with 0 disp8)

Many instructions, particularly variants of 'get' and 'advance' -- end up encoding the exact same instructions.
But the types differ, and the type-checker checks them differently.

=== Advanced checks

Couple of items require inserting mapping to multiple instructions:
  bounds checking against array length in 'advance'
  dereferencing 'ref' types (see type list up top)

A. Dereferencing a ref

    tmp/EDX <- advance *s, tmp0/EDI
      => compare (ESP+4), *(ESP+8)  ; '*' from compiler2
         jump-unless-equal panic
         EDX <- add ESP, 8
         EDX <- copy *EDX
         EDX <- add EDX, 4
         EDX <- 8d/lea EDX + result

=== More speculative ideas

Initialize data segment with special extensible syntax for literals. All
literals except numbers and strings start with %.

  %size(type) => compiler replaces with size of type
  %point(3, 4) => two words

and so on.

=== Credits

Forth
C
Rust
Lisp
qhasm
span class="k">text-decoration: underline; } --> </style> <script type='text/javascript'> <!-- /* function to open any folds containing a jumped-to line before jumping to it */ function JumpToLine() { var lineNum; lineNum = window.location.hash; lineNum = lineNum.substr(1); /* strip off '#' */ if (lineNum.indexOf('L') == -1) { lineNum = 'L'+lineNum; } var lineElem = document.getElementById(lineNum); /* Always jump to new location even if the line was hidden inside a fold, or * we corrected the raw number to a line ID. */ if (lineElem) { lineElem.scrollIntoView(true); } return true; } if ('onhashchange' in window) { window.onhashchange = JumpToLine; } --> </script> </head> <body onload='JumpToLine();'> <a href='https://github.com/akkartik/mu/blob/master/061read-byte.subx'>https://github.com/akkartik/mu/blob/master/061read-byte.subx</a> <pre id='vimCodeElement'> <span id="L1" class="LineNr"> 1 </span><span class="subxComment"># read-byte-buffered: one higher-level abstraction atop 'read'.</span> <span id="L2" class="LineNr"> 2 </span><span class="subxComment">#</span> <span id="L3" class="LineNr"> 3 </span><span class="subxComment"># There are many situations where 'read' is a lot to manage, and we need</span> <span id="L4" class="LineNr"> 4 </span><span class="subxComment"># to abstract some details away. One of them is when we want to read a file</span> <span id="L5" class="LineNr"> 5 </span><span class="subxComment"># character by character. In this situation we follow C's FILE data structure,</span> <span id="L6" class="LineNr"> 6 </span><span class="subxComment"># which manages the underlying file descriptor together with the buffer it</span> <span id="L7" class="LineNr"> 7 </span><span class="subxComment"># reads into. We call our version 'buffered-file'. Should be useful with other</span> <span id="L8" class="LineNr"> 8 </span><span class="subxComment"># primitives as well, in later layers.</span> <span id="L9" class="LineNr"> 9 </span> <span id="L10" class="LineNr"> 10 </span>== data <span id="L11" class="LineNr"> 11 </span> <span id="L12" class="LineNr"> 12 </span><span class="subxComment"># The buffered file for standard input. Also illustrates the layout for</span> <span id="L13" class="LineNr"> 13 </span><span class="subxComment"># buffered-file: a pointer to the backing store, followed by a 'buffer' stream</span> <span id="L14" class="LineNr"> 14 </span><span class="SpecialChar">Stdin</span>: <span class="subxComment"># buffered-file</span> <span id="L15" class="LineNr"> 15 </span> <span class="subxComment"># file descriptor or (addr stream byte)</span> <span id="L16" class="LineNr"> 16 </span> 0/imm32 <span class="subxComment"># standard input</span> <span id="L17" class="LineNr"> 17 </span><span class="Constant">$Stdin-&gt;buffer</span>: <span id="L18" class="LineNr"> 18 </span> <span class="subxComment"># inlined fields for a stream</span> <span id="L19" class="LineNr"> 19 </span> <span class="subxComment"># current write index</span> <span id="L20" class="LineNr"> 20 </span> 0/imm32 <span id="L21" class="LineNr"> 21 </span> <span class="subxComment"># current read index</span> <span id="L22" class="LineNr"> 22 </span> 0/imm32 <span id="L23" class="LineNr"> 23 </span> <span class="subxComment"># size</span> <span id="L24" class="LineNr"> 24 </span> 8/imm32 <span id="L25" class="LineNr"> 25 </span> <span class="subxComment"># data</span> <span id="L26" class="LineNr"> 26 </span> 00 00 00 00 00 00 00 00 <span class="subxComment"># 8 bytes</span> <span id="L27" class="LineNr"> 27 </span> <span id="L28" class="LineNr"> 28 </span><span class="subxComment"># TODO: 8 bytes is too small. We'll need to grow the buffer for efficiency. But</span> <span id="L29" class="LineNr"> 29 </span><span class="subxComment"># I don't want to type in 1024 bytes here.</span> <span id="L30" class="LineNr"> 30 </span> <span id="L31" class="LineNr"> 31 </span>== code <span id="L32" class="LineNr"> 32 </span><span class="subxComment"># instruction effective address register displacement immediate</span> <span id="L33" class="LineNr"> 33 </span><span class="subxS1Comment"># . op subop mod rm32 base index scale r32</span> <span id="L34" class="LineNr"> 34 </span><span class="subxS1Comment"># . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes</span> <span id="L35" class="LineNr"> 35 </span> <span id="L36" class="LineNr"> 36 </span><span class="subxComment"># return next byte value in eax, with top 3 bytes cleared.</span> <span id="L37" class="LineNr"> 37 </span><span class="subxComment"># On reaching end of file, return 0xffffffff (Eof).</span> <span id="L38" class="LineNr"> 38 </span><span class="subxFunction">read-byte-buffered</span>: <span class="subxComment"># f: (addr buffered-file) -&gt; byte-or-Eof/eax</span> <span id="L39" class="LineNr"> 39 </span> <span class="subxS1Comment"># . prologue</span> <span id="L40" class="LineNr"> 40 </span> 55/push-ebp <span id="L41" class="LineNr"> 41 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> <span id="L42" class="LineNr"> 42 </span> <span class="subxS1Comment"># . save registers</span> <span id="L43" class="LineNr"> 43 </span> 51/push-ecx <span id="L44" class="LineNr"> 44 </span> 56/push-esi <span id="L45" class="LineNr"> 45 </span> <span class="subxComment"># esi = f</span> <span id="L46" class="LineNr"> 46 </span> 8b/copy 1/mod/*+disp8 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 6/r32/esi 8/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(ebp+8) to esi</span> <span id="L47" class="LineNr"> 47 </span> <span class="subxComment"># ecx = f-&gt;read</span> <span id="L48" class="LineNr"> 48 </span> 8b/copy 1/mod/*+disp8 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx 8/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(esi+8) to ecx</span> <span id="L49" class="LineNr"> 49 </span> <span class="subxComment"># if (f-&gt;read &gt;= f-&gt;write) populate stream from file</span> <span id="L50" class="LineNr"> 50 </span> 3b/compare 1/mod/*+disp8 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># compare ecx with *(esi+4)</span> <span id="L51" class="LineNr"> 51 </span> 7c/jump-if-&lt; $read-byte-buffered:from-stream/disp8 <span id="L52" class="LineNr"> 52 </span> <span class="subxS1Comment"># . clear-stream(stream = f+4)</span> <span id="L53" class="LineNr"> 53 </span> <span class="subxS2Comment"># . . push args</span> <span id="L54" class="LineNr"> 54 </span> 8d/copy-address 1/mod/*+disp8 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0/r32/eax 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy esi+4 to eax</span> <span id="L55" class="LineNr"> 55 </span> 50/push-eax <span id="L56" class="LineNr"> 56 </span> <span class="subxS2Comment"># . . call</span> <span id="L57" class="LineNr"> 57 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L58" class="LineNr"> 58 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L59" class="LineNr"> 59 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L60" class="LineNr"> 60 </span> <span class="subxS1Comment"># . f-&gt;read must now be 0; update its cache at ecx</span> <span id="L61" class="LineNr"> 61 </span> 31/xor 3/mod/direct 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># clear ecx</span> <span id="L62" class="LineNr"> 62 </span> <span class="subxS1Comment"># . eax = read(f-&gt;fd, stream = f+4)</span> <span id="L63" class="LineNr"> 63 </span> <span class="subxS2Comment"># . . push args</span> <span id="L64" class="LineNr"> 64 </span> 50/push-eax <span id="L65" class="LineNr"> 65 </span> ff 6/subop/push 0/mod/indirect 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># push *esi</span> <span id="L66" class="LineNr"> 66 </span> <span class="subxS2Comment"># . . call</span> <span id="L67" class="LineNr"> 67 </span> e8/call <a href='060read.subx.html#L48'>read</a>/disp32 <span id="L68" class="LineNr"> 68 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L69" class="LineNr"> 69 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> <span id="L70" class="LineNr"> 70 </span> <span class="subxComment"># if (eax == 0) return 0xffffffff</span> <span id="L71" class="LineNr"> 71 </span> 3d/compare-eax-and 0/imm32 <span id="L72" class="LineNr"> 72 </span> 75/jump-if-!= $read-byte-buffered:from-stream/disp8 <span id="L73" class="LineNr"> 73 </span> b8/copy-to-eax 0xffffffff/imm32/Eof <span id="L74" class="LineNr"> 74 </span> eb/jump $read-byte-buffered:end/disp8 <span id="L75" class="LineNr"> 75 </span><span class="Constant">$read-byte-buffered:from-stream</span>: <span id="L76" class="LineNr"> 76 </span> <span class="subxComment"># byte-or-Eof = f-&gt;data[f-&gt;read]</span> <span id="L77" class="LineNr"> 77 </span> 31/xor 3/mod/direct 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0/r32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># clear eax</span> <span id="L78" class="LineNr"> 78 </span> 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx <span class="Normal"> . </span> 0/r32/AL 0x10/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy byte at *(esi+ecx+16) to AL</span> <span id="L79" class="LineNr"> 79 </span> <span class="subxComment"># ++f-&gt;read</span> <span id="L80" class="LineNr"> 80 </span> ff 0/subop/increment 1/mod/*+disp8 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/disp8 <span class="Normal"> . </span> <span class="subxComment"># increment *(esi+8)</span> <span id="L81" class="LineNr"> 81 </span><span class="Constant">$read-byte-buffered:end</span>: <span id="L82" class="LineNr"> 82 </span> <span class="subxS1Comment"># . restore registers</span> <span id="L83" class="LineNr"> 83 </span> 5e/pop-to-esi <span id="L84" class="LineNr"> 84 </span> 59/pop-to-ecx <span id="L85" class="LineNr"> 85 </span> <span class="subxS1Comment"># . epilogue</span> <span id="L86" class="LineNr"> 86 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> <span id="L87" class="LineNr"> 87 </span> 5d/pop-to-ebp <span id="L88" class="LineNr"> 88 </span> c3/return <span id="L89" class="LineNr"> 89 </span> <span id="L90" class="LineNr"> 90 </span><span class="subxH1Comment"># - tests</span> <span id="L91" class="LineNr"> 91 </span> <span id="L92" class="LineNr"> 92 </span><span class="subxTest">test-read-byte-buffered-single</span>: <span id="L93" class="LineNr"> 93 </span> <span class="subxH1Comment"># - check that read-byte-buffered returns first byte of 'file'</span> <span id="L94" class="LineNr"> 94 </span> <span class="subxComment"># setup</span> <span id="L95" class="LineNr"> 95 </span> <span class="subxS1Comment"># . clear-stream(_test-stream)</span> <span id="L96" class="LineNr"> 96 </span> <span class="subxS2Comment"># . . push args</span> <span id="L97" class="LineNr"> 97 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L98" class="LineNr"> 98 </span> <span class="subxS2Comment"># . . call</span> <span id="L99" class="LineNr"> 99 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L100" class="LineNr">100 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L101" class="LineNr">101 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L102" class="LineNr">102 </span> <span class="subxS1Comment"># . clear-stream(_test-buffered-file-&gt;buffer)</span> <span id="L103" class="LineNr">103 </span> <span class="subxS2Comment"># . . push args</span> <span id="L104" class="LineNr">104 </span> 68/push $_test-buffered-file-&gt;buffer/imm32 <span id="L105" class="LineNr">105 </span> <span class="subxS2Comment"># . . call</span> <span id="L106" class="LineNr">106 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L107" class="LineNr">107 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L108" class="LineNr">108 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L109" class="LineNr">109 </span> <span class="subxS1Comment"># . write(_test-stream, &quot;Ab&quot;)</span> <span id="L110" class="LineNr">110 </span> <span class="subxS2Comment"># . . push args</span> <span id="L111" class="LineNr">111 </span> 68/push <span class="Constant">&quot;Ab&quot;</span>/imm32 <span id="L112" class="LineNr">112 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L113" class="LineNr">113 </span> <span class="subxS2Comment"># . . call</span> <span id="L114" class="LineNr">114 </span> e8/call <a href='057write.subx.html#L24'>write</a>/disp32 <span id="L115" class="LineNr">115 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L116" class="LineNr">116 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> <span id="L117" class="LineNr">117 </span> <span class="subxComment"># read-byte-buffered(_test-buffered-file)</span> <span id="L118" class="LineNr">118 </span> <span class="subxS2Comment"># . . push args</span> <span id="L119" class="LineNr">119 </span> 68/push <a href='061read-byte.subx.html#L274'>_test-buffered-file</a>/imm32 <span id="L120" class="LineNr">120 </span> <span class="subxS2Comment"># . . call</span> <span id="L121" class="LineNr">121 </span> e8/call <a href='061read-byte.subx.html#L38'>read-byte-buffered</a>/disp32 <span id="L122" class="LineNr">122 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L123" class="LineNr">123 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L124" class="LineNr">124 </span> <span class="subxComment"># check-ints-equal(eax, 'A', msg)</span> <span id="L125" class="LineNr">125 </span> <span class="subxS2Comment"># . . push args</span> <span id="L126" class="LineNr">126 </span> 68/push <span class="Constant">&quot;F - test-read-byte-buffered-single&quot;</span>/imm32 <span id="L127" class="LineNr">127 </span> 68/push 0x41/imm32 <span id="L128" class="LineNr">128 </span> 50/push-eax <span id="L129" class="LineNr">129 </span> <span class="subxS2Comment"># . . call</span> <span id="L130" class="LineNr">130 </span> e8/call <a href='051test.subx.html#L24'>check-ints-equal</a>/disp32 <span id="L131" class="LineNr">131 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L132" class="LineNr">132 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> <span id="L133" class="LineNr">133 </span> <span class="subxS1Comment"># . end</span> <span id="L134" class="LineNr">134 </span> c3/return <span id="L135" class="LineNr">135 </span> <span id="L136" class="LineNr">136 </span><span class="subxTest">test-read-byte-buffered-multiple</span>: <span id="L137" class="LineNr">137 </span> <span class="subxH1Comment"># - call read-byte-buffered twice, check that second call returns second byte</span> <span id="L138" class="LineNr">138 </span> <span class="subxComment"># setup</span> <span id="L139" class="LineNr">139 </span> <span class="subxS1Comment"># . clear-stream(_test-stream)</span> <span id="L140" class="LineNr">140 </span> <span class="subxS2Comment"># . . push args</span> <span id="L141" class="LineNr">141 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L142" class="LineNr">142 </span> <span class="subxS2Comment"># . . call</span> <span id="L143" class="LineNr">143 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L144" class="LineNr">144 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L145" class="LineNr">145 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L146" class="LineNr">146 </span> <span class="subxS1Comment"># . clear-stream($_test-buffered-file-&gt;buffer)</span> <span id="L147" class="LineNr">147 </span> <span class="subxS2Comment"># . . push args</span> <span id="L148" class="LineNr">148 </span> 68/push $_test-buffered-file-&gt;buffer/imm32 <span id="L149" class="LineNr">149 </span> <span class="subxS2Comment"># . . call</span> <span id="L150" class="LineNr">150 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L151" class="LineNr">151 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L152" class="LineNr">152 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L153" class="LineNr">153 </span> <span class="subxS1Comment"># . write(_test-stream, &quot;Ab&quot;)</span> <span id="L154" class="LineNr">154 </span> <span class="subxS2Comment"># . . push args</span> <span id="L155" class="LineNr">155 </span> 68/push <span class="Constant">&quot;Ab&quot;</span>/imm32 <span id="L156" class="LineNr">156 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L157" class="LineNr">157 </span> <span class="subxS2Comment"># . . call</span> <span id="L158" class="LineNr">158 </span> e8/call <a href='057write.subx.html#L24'>write</a>/disp32 <span id="L159" class="LineNr">159 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L160" class="LineNr">160 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> <span id="L161" class="LineNr">161 </span> <span class="subxComment"># read-byte-buffered(_test-buffered-file)</span> <span id="L162" class="LineNr">162 </span> <span class="subxS2Comment"># . . push args</span> <span id="L163" class="LineNr">163 </span> 68/push <a href='061read-byte.subx.html#L274'>_test-buffered-file</a>/imm32 <span id="L164" class="LineNr">164 </span> <span class="subxS2Comment"># . . call</span> <span id="L165" class="LineNr">165 </span> e8/call <a href='061read-byte.subx.html#L38'>read-byte-buffered</a>/disp32 <span id="L166" class="LineNr">166 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L167" class="LineNr">167 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L168" class="LineNr">168 </span> <span class="subxComment"># read-byte-buffered(_test-buffered-file)</span> <span id="L169" class="LineNr">169 </span> <span class="subxS2Comment"># . . push args</span> <span id="L170" class="LineNr">170 </span> 68/push <a href='061read-byte.subx.html#L274'>_test-buffered-file</a>/imm32 <span id="L171" class="LineNr">171 </span> <span class="subxS2Comment"># . . call</span> <span id="L172" class="LineNr">172 </span> e8/call <a href='061read-byte.subx.html#L38'>read-byte-buffered</a>/disp32 <span id="L173" class="LineNr">173 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L174" class="LineNr">174 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L175" class="LineNr">175 </span> <span class="subxComment"># check-ints-equal(eax, 'b', msg)</span> <span id="L176" class="LineNr">176 </span> <span class="subxS2Comment"># . . push args</span> <span id="L177" class="LineNr">177 </span> 68/push <span class="Constant">&quot;F - test-read-byte-buffered-multiple&quot;</span>/imm32 <span id="L178" class="LineNr">178 </span> 68/push 0x62/imm32 <span id="L179" class="LineNr">179 </span> 50/push-eax <span id="L180" class="LineNr">180 </span> <span class="subxS2Comment"># . . call</span> <span id="L181" class="LineNr">181 </span> e8/call <a href='051test.subx.html#L24'>check-ints-equal</a>/disp32 <span id="L182" class="LineNr">182 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L183" class="LineNr">183 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> <span id="L184" class="LineNr">184 </span> <span class="subxS1Comment"># . end</span> <span id="L185" class="LineNr">185 </span> c3/return <span id="L186" class="LineNr">186 </span> <span id="L187" class="LineNr">187 </span><span class="subxTest">test-read-byte-buffered-end-of-file</span>: <span id="L188" class="LineNr">188 </span> <span class="subxH1Comment"># - call read-byte-buffered on an empty 'file', check that it returns Eof</span> <span id="L189" class="LineNr">189 </span> <span class="subxComment"># setup</span> <span id="L190" class="LineNr">190 </span> <span class="subxS1Comment"># . clear-stream(_test-stream)</span> <span id="L191" class="LineNr">191 </span> <span class="subxS2Comment"># . . push args</span> <span id="L192" class="LineNr">192 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L193" class="LineNr">193 </span> <span class="subxS2Comment"># . . call</span> <span id="L194" class="LineNr">194 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L195" class="LineNr">195 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L196" class="LineNr">196 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L197" class="LineNr">197 </span> <span class="subxS1Comment"># . clear-stream($_test-buffered-file-&gt;buffer)</span> <span id="L198" class="LineNr">198 </span> <span class="subxS2Comment"># . . push args</span> <span id="L199" class="LineNr">199 </span> 68/push $_test-buffered-file-&gt;buffer/imm32 <span id="L200" class="LineNr">200 </span> <span class="subxS2Comment"># . . call</span> <span id="L201" class="LineNr">201 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L202" class="LineNr">202 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L203" class="LineNr">203 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L204" class="LineNr">204 </span> <span class="subxComment"># read-byte-buffered(_test-buffered-file)</span> <span id="L205" class="LineNr">205 </span> <span class="subxS2Comment"># . . push args</span> <span id="L206" class="LineNr">206 </span> 68/push <a href='061read-byte.subx.html#L274'>_test-buffered-file</a>/imm32 <span id="L207" class="LineNr">207 </span> <span class="subxS2Comment"># . . call</span> <span id="L208" class="LineNr">208 </span> e8/call <a href='061read-byte.subx.html#L38'>read-byte-buffered</a>/disp32 <span id="L209" class="LineNr">209 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L210" class="LineNr">210 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L211" class="LineNr">211 </span> <span class="subxComment"># check-ints-equal(eax, 0xffffffff, msg)</span> <span id="L212" class="LineNr">212 </span> <span class="subxS2Comment"># . . push args</span> <span id="L213" class="LineNr">213 </span> 68/push <span class="Constant">&quot;F - test-read-byte-buffered-end-of-file&quot;</span>/imm32 <span id="L214" class="LineNr">214 </span> 68/push 0xffffffff/imm32/Eof <span id="L215" class="LineNr">215 </span> 50/push-eax <span id="L216" class="LineNr">216 </span> <span class="subxS2Comment"># . . call</span> <span id="L217" class="LineNr">217 </span> e8/call <a href='051test.subx.html#L24'>check-ints-equal</a>/disp32 <span id="L218" class="LineNr">218 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L219" class="LineNr">219 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> <span id="L220" class="LineNr">220 </span> <span class="subxS1Comment"># . end</span> <span id="L221" class="LineNr">221 </span> c3/return <span id="L222" class="LineNr">222 </span> <span id="L223" class="LineNr">223 </span><span class="subxTest">test-read-byte-buffered-refills-buffer</span>: <span id="L224" class="LineNr">224 </span> <span class="subxH1Comment"># - consume buffered-file's buffer, check that next read-byte-buffered still works</span> <span id="L225" class="LineNr">225 </span> <span class="subxComment"># setup</span> <span id="L226" class="LineNr">226 </span> <span class="subxS1Comment"># . clear-stream(_test-stream)</span> <span id="L227" class="LineNr">227 </span> <span class="subxS2Comment"># . . push args</span> <span id="L228" class="LineNr">228 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L229" class="LineNr">229 </span> <span class="subxS2Comment"># . . call</span> <span id="L230" class="LineNr">230 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L231" class="LineNr">231 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L232" class="LineNr">232 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L233" class="LineNr">233 </span> <span class="subxS1Comment"># . clear-stream($_test-buffered-file-&gt;buffer)</span> <span id="L234" class="LineNr">234 </span> <span class="subxS2Comment"># . . push args</span> <span id="L235" class="LineNr">235 </span> 68/push $_test-buffered-file-&gt;buffer/imm32 <span id="L236" class="LineNr">236 </span> <span class="subxS2Comment"># . . call</span> <span id="L237" class="LineNr">237 </span> e8/call <a href='055stream.subx.html#L17'>clear-stream</a>/disp32 <span id="L238" class="LineNr">238 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L239" class="LineNr">239 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L240" class="LineNr">240 </span> <span class="subxS1Comment"># . write(_test-stream, &quot;Abcdefgh&quot;)</span> <span id="L241" class="LineNr">241 </span> <span class="subxS2Comment"># . . push args</span> <span id="L242" class="LineNr">242 </span> 68/push <span class="Constant">&quot;Abcdefgh&quot;</span>/imm32 <span id="L243" class="LineNr">243 </span> 68/push <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L244" class="LineNr">244 </span> <span class="subxS2Comment"># . . call</span> <span id="L245" class="LineNr">245 </span> e8/call <a href='057write.subx.html#L24'>write</a>/disp32 <span id="L246" class="LineNr">246 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L247" class="LineNr">247 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> <span id="L248" class="LineNr">248 </span> <span class="subxComment"># pretend buffer is full</span> <span id="L249" class="LineNr">249 </span> <span class="subxS1Comment"># . _test-buffered-file-&gt;read = 6 # &gt;= _test-buffered-file-&gt;size</span> <span id="L250" class="LineNr">250 </span> b8/copy-to-eax <a href='061read-byte.subx.html#L274'>_test-buffered-file</a>/imm32 <span id="L251" class="LineNr">251 </span> c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/disp8 6/imm32 <span class="subxComment"># copy to *(eax+8)</span> <span id="L252" class="LineNr">252 </span> <span class="subxComment"># read-byte-buffered(_test-buffered-file)</span> <span id="L253" class="LineNr">253 </span> <span class="subxS2Comment"># . . push args</span> <span id="L254" class="LineNr">254 </span> 68/push <a href='061read-byte.subx.html#L274'>_test-buffered-file</a>/imm32 <span id="L255" class="LineNr">255 </span> <span class="subxS2Comment"># . . call</span> <span id="L256" class="LineNr">256 </span> e8/call <a href='061read-byte.subx.html#L38'>read-byte-buffered</a>/disp32 <span id="L257" class="LineNr">257 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L258" class="LineNr">258 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> <span id="L259" class="LineNr">259 </span> <span class="subxComment"># check-ints-equal(eax, 'A', msg)</span> <span id="L260" class="LineNr">260 </span> <span class="subxS2Comment"># . . push args</span> <span id="L261" class="LineNr">261 </span> 68/push <span class="Constant">&quot;F - test-read-byte-buffered-refills-buffer&quot;</span>/imm32 <span id="L262" class="LineNr">262 </span> 68/push 0x41/imm32 <span id="L263" class="LineNr">263 </span> 50/push-eax <span id="L264" class="LineNr">264 </span> <span class="subxS2Comment"># . . call</span> <span id="L265" class="LineNr">265 </span> e8/call <a href='051test.subx.html#L24'>check-ints-equal</a>/disp32 <span id="L266" class="LineNr">266 </span> <span class="subxS2Comment"># . . discard args</span> <span id="L267" class="LineNr">267 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> <span id="L268" class="LineNr">268 </span> <span class="subxS1Comment"># . end</span> <span id="L269" class="LineNr">269 </span> c3/return <span id="L270" class="LineNr">270 </span> <span id="L271" class="LineNr">271 </span>== data <span id="L272" class="LineNr">272 </span> <span id="L273" class="LineNr">273 </span><span class="subxComment"># a test buffered file for _test-stream</span> <span id="L274" class="LineNr">274 </span><span class="subxMinorFunction">_test-buffered-file</span>: <span class="subxComment"># buffered-file</span> <span id="L275" class="LineNr">275 </span> <span class="subxComment"># file descriptor or (addr stream byte)</span> <span id="L276" class="LineNr">276 </span> <a href='057write.subx.html#L148'>_test-stream</a>/imm32 <span id="L277" class="LineNr">277 </span><span class="Constant">$_test-buffered-file-&gt;buffer</span>: <span id="L278" class="LineNr">278 </span> <span class="subxComment"># current write index</span> <span id="L279" class="LineNr">279 </span> 0/imm32 <span id="L280" class="LineNr">280 </span> <span class="subxComment"># current read index</span> <span id="L281" class="LineNr">281 </span> 0/imm32 <span id="L282" class="LineNr">282 </span> <span class="subxComment"># size</span> <span id="L283" class="LineNr">283 </span> 6/imm32 <span id="L284" class="LineNr">284 </span> <span class="subxComment"># data</span> <span id="L285" class="LineNr">285 </span> 00 00 00 00 00 00 <span class="subxComment"># 6 bytes</span> <span id="L286" class="LineNr">286 </span> <span id="L287" class="LineNr">287 </span><span class="subxMinorFunction">_test-input-stream</span>: <span class="subxComment"># (stream byte)</span> <span id="L288" class="LineNr">288 </span> <span class="subxComment"># current write index</span> <span id="L289" class="LineNr">289 </span> 0/imm32 <span id="L290" class="LineNr">290 </span> <span class="subxComment"># current read index</span> <span id="L291" class="LineNr">291 </span> 0/imm32 <span id="L292" class="LineNr">292 </span> <span class="subxComment"># size</span> <span id="L293" class="LineNr">293 </span> 0x100/imm32 <span class="subxComment"># 256 bytes</span> <span id="L294" class="LineNr">294 </span> <span class="subxComment"># data (16 lines x 16 bytes/line)</span> <span id="L295" class="LineNr">295 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L296" class="LineNr">296 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L297" class="LineNr">297 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L298" class="LineNr">298 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L299" class="LineNr">299 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L300" class="LineNr">300 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L301" class="LineNr">301 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L302" class="LineNr">302 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L303" class="LineNr">303 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L304" class="LineNr">304 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L305" class="LineNr">305 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L306" class="LineNr">306 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L307" class="LineNr">307 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L308" class="LineNr">308 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L309" class="LineNr">309 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L310" class="LineNr">310 </span> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <span id="L311" class="LineNr">311 </span> <span id="L312" class="LineNr">312 </span><span class="subxComment"># a test buffered file for _test-input-stream</span> <span id="L313" class="LineNr">313 </span><span class="subxMinorFunction">_test-input-buffered-file</span>: <span class="subxComment"># buffered-file</span> <span id="L314" class="LineNr">314 </span> <span class="subxComment"># file descriptor or (addr stream byte)</span> <span id="L315" class="LineNr">315 </span> <a href='061read-byte.subx.html#L287'>_test-input-stream</a>/imm32 <span id="L316" class="LineNr">316 </span><span class="Constant">$_test-input-buffered-file-&gt;buffer</span>: <span id="L317" class="LineNr">317 </span> <span class="subxComment"># current write index</span> <span id="L318" class="LineNr">318 </span> 0/imm32 <span id="L319" class="LineNr">319 </span> <span class="subxComment"># current read index</span> <span id="L320" class="LineNr">320 </span> 0/imm32 <span id="L321" class="LineNr">321 </span> <span class="subxComment"># size</span> <span id="L322" class="LineNr">322 </span> 6/imm32 <span id="L323" class="LineNr">323 </span> <span class="subxComment"># data</span> <span id="L324" class="LineNr">324 </span> 00 00 00 00 00 00 <span class="subxComment"># 6 bytes</span> <span id="L325" class="LineNr">325 </span> <span id="L326" class="LineNr">326 </span><span class="subxS2Comment"># . . vim&#0058;nowrap:textwidth=0</span> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->