Now that we have a binary file (foo.o) it is time to open it with poke. There are two ways to do that.
One way is to pass the name of the file in the poke invocation. The program will start, open the file, and present you with the REPL, like in:
$ poke foo.o […] (poke)
The other way is to fire up poke without arguments, and then use the
.file
dot-command to open the file:
$ poke […] (poke) .file foo.o The current IOS is now `./foo.o'. (poke)
Note how poke replies to the dot-command, stating that the current IOS is now the file we opened.
You may be wondering, what is this IOS thing? It is an acronym for Input/Output Space, often written IO Space. This is the denomination used to refer to the entities being edited with poke. In this case the IO space being edited is a file, but we will see that is not always the case: poke can also edit other entities such as memory buffers and remote block-oriented devices over the network. For now, let’s keep in mind that IOS, or IO space, refers to the file being edited.
And why “current”? GNU poke is capable of editing several files (more generally, several IO spaces) simultaneously. At any time, one of these files is the “current one”. In our case, the current IO space is the file foo.o, since it is the only file poke knows about:
(poke) .info ios Id Type Mode Bias Size Name * 0 FILE rw 0x00000000#B 0x00000398#B ./foo.o
The command .info ios
gives us information about all the IO
spaces that are currently open. The first column tells us a positive
integer that identifies the IOS. This IO space identifier is
unique at any given time. In this example, the id corresponding to
foo.o is 0
. The second column tells us the type of IO
space. The third column tells us that foo.o allows both reading
and writing. The fourth column tells us the size of the file, in
hexadecimal. The fifth column is the name of the IO space; in this
case, it is the path to the file being edited.
You may wonder what is that weird suffix #B
. It is a unit,
and tells us that the size 0x398
is measured in bytes, i.e. the
size of foo.o is 0x398
bytes (or, in decimal, 920
bytes.)
Finally, the asterisk character at the left of the entry for foo.o identifies it as the current IO space. To see this more clearly, let’s open another file:
(poke) .file bar.o The current IOS is now `./bar.o'. (poke) .info ios Id Type Mode Bias Size Name * 1 FILE rw 0x00000000#B 0x00000398#B ./bar.o 0 FILE rw 0x00000000#B 0x00000398#B ./foo.o
Ah, there we have both foo.o and bar.o. Now the current
IO space (the entry featuring the asterisk at the left) is the file
that we just opened, bar.o. This is because poke always sets
the most recently open file as the current one. We can switch back to
foo.o using yet another dot-command, .ios
, which gets
an IO space as an argument:
(poke) .ios 0 The current IOS is now `./foo.o'. (poke) .info ios Id Type Mode Bias Size Name 1 FILE rw 0x00000000#B 0x00000398#B ./bar.o * 0 FILE rw 0x00000000#B 0x00000398#B ./foo.o
We are back to foo.o. Since we are not really interested in bar.o, let’s close it:
(poke) .close 1 (poke) .info ios Id Type Mode Bias Size Name * 0 FILE rw 0x00000000#B 0x00000398#B ./foo.o
Note how in the examples above we used the IO space identifiers (0 and
1) in order to refer to them. This can be inconvenient, as these ids
are not memorable at all. Fortunately it is also possible to refer to
an IO space by name using the $<name>
construct, like
this:
(poke) .ios $<./foo.o> The current IOS is now `./foo.o'. (poke) .close $<./bar.o>
Awesome. Now we can focus on foo.o’s contents…