We are developing an operating system for my personal research
and practical education.
For the academic purpose, this motivation is similar to MINIX,
but we do not focus on theories.
Our main objective is to provide knowledges on hardware-related
programming. This is one of the most difficult and complex parts
when we start the development of operating system from scratch.
This checkpoint is a small extension from the checkpoint 1 although
many lines of code are added.
This includes two main updates from the checkpoint 1:
1) This supports to read multiple sectors for the other program.
2) This displays the error code in case of disk read failure.
The following four instructions collectively perform to convert
a 4-bit value into a hex-decimal character.
The sbb instruction subtracts the first (in gas style) operand from the second operand
then stores the result in the second operand, if the carry flag (CF) is cleared.
If CF is set, the sbb instruction subtracts the first operand plus one
from the second operand, then stores the result in the second operand.
Thus, Line 2 subtracts 0x6a if the input 4-bit value is less than 10,
In the same way, it subtracts 0x69 if the input 4-bit value is not less than 10,
With these instructions, the result is;
1) 0x96 + AL if AL in [0, 9] with set AF,
and 2) 0xa1 + AL - 0xa if AL in [10, 15] with cleared AF.
Here, subtracting 0x6a from a value in the range from 0 to 9
borrows out of bit 3 of the result, and consequently,
the adjust flag (AF) is set.
On the other hand, subtracting 0x69 from a value
in the range from 10 (0x0a) to 15, does not borrow out of bit 3 of the result,
hence AF is cleared.
Although the das instruction is more complex than explained here,
Line 3 subtracts 0x66 and 0x60 if AF is set and cleared, respectively.
Thus, we can convert the 4-bit value in [0, 15]
to an ascii character 0–9A–F.
The orb instruction decapitalizes an alphabetic character, A–F
while taking no effect on a numeric character, 0–9.
cmpb $0xa,%al /* CF=1 if %al < $0xa (0..9) */
sbbb $0x69,%al /* %al <= %al - ($0x69 + CF) */
das /* BCD (N.B., %al - 0x60 if AF is not set) */
orb $0x20,%al /* To lower case */
The following ascii code set helps you understand this set of instructions.
The sbb and das instructions project a value from 0–15
into two contiguous sets 0–1 and A–F,
skipping seven (six by das plus one by CF of sbb) characters (:;<=>?@).
30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7
38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ?
40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G
48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O
50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W
58 X 59 Y 5a Z 5b [ 5c \ 5d ] 5e ^ 5f _
60 ` 61 a 62 b 63 c 64 d 65 e 66 f 67 g
We try to read sectors one by one
although the “Read Sectors From Drive” function
can read multiple sectors.
This is because it sometimes causes an error
when it reads across different tracks/heads.
Emperically, it may fail to read several sectors
across different tracks/heads without reporting any errors.
We can align the range with the boundaries,
but it is a little complex and the overhead of one-by-one read
is ignorable for us in this step
(but perhaps not negligible for computers).