Source string Read only

(itstool) path: sect1/para
358/3580
Context English State
Go ahead, and save the code in a file named <filename>hex.asm</filename>, then type the following (the <userinput>^D</userinput> means press the control key and type <userinput>D</userinput> while holding the control key down):
<prompt>%</prompt> <userinput>nasm -f elf hex.asm</userinput>
<prompt>%</prompt> <userinput>ld -s -o hex hex.o</userinput>
<prompt>%</prompt> <userinput>./hex</userinput>
<userinput>Hello, World!</userinput>
48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0A <userinput>Here I come!</userinput>
48 65 72 65 20 49 20 63 6F 6D 65 21 0A <userinput>^D</userinput> <prompt>%</prompt>
If you are migrating to <trademark class="registered">UNIX</trademark> from <acronym><trademark class="registered">MS-DOS</trademark></acronym>, you may be wondering why each line ends with <constant>0A</constant> instead of <constant>0D 0A</constant>. This is because <trademark class="registered">UNIX</trademark> does not use the cr/lf convention, but a "new line" convention, which is <constant>0A</constant> in hexadecimal.
Can we improve this? Well, for one, it is a bit confusing because once we have converted a line of text, our input no longer starts at the beginning of the line. We can modify it to print a new line instead of a space after each <constant>0A</constant>:
%include 'system.inc'

section .data
hex db '0123456789ABCDEF'
buffer db 0, 0, ' '

section .text
global _start
_start:
mov cl, ' '

.loop:
; read a byte from stdin
push dword 1
push dword buffer
push dword stdin
sys.read
add esp, byte 12
or eax, eax
je .done

; convert it to hex
movzx eax, byte [buffer]
mov [buffer+2], cl
cmp al, 0Ah
jne .hex
mov [buffer+2], al

.hex:
mov edx, eax
shr dl, 4
mov dl, [hex+edx]
mov [buffer], dl
and al, 0Fh
mov al, [hex+eax]
mov [buffer+1], al

; print it
push dword 3
push dword buffer
push dword stdout
sys.write
add esp, byte 12
jmp short .loop

.done:
push dword 0
sys.exit
We have stored the space in the <varname role="register">CL</varname> register. We can do this safely because, unlike <trademark class="registered">Microsoft</trademark> <trademark class="registered">Windows</trademark>, <trademark class="registered">UNIX</trademark> system calls do not modify the value of any register they do not use to return a value in.
That means we only need to set <varname role="register">CL</varname> once. We have, therefore, added a new label <varname>.loop</varname> and jump to it for the next byte instead of jumping at <varname>_start</varname>. We have also added the <varname>.hex</varname> label so we can either have a blank space or a new line as the third byte of the <varname>buffer</varname>.
Once you have changed <filename>hex.asm</filename> to reflect these changes, type:
<prompt>%</prompt> <userinput>nasm -f elf hex.asm</userinput>
<prompt>%</prompt> <userinput>ld -s -o hex hex.o</userinput>
<prompt>%</prompt> <userinput>./hex</userinput>
<userinput>Hello, World!</userinput>
48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0A
<userinput>Here I come!</userinput>
48 65 72 65 20 49 20 63 6F 6D 65 21 0A
<userinput>^D</userinput> <prompt>%</prompt>
That looks better. But this code is quite inefficient! We are making a system call for every single byte twice (once to read it, another time to write the output).
Buffered Input and Output

Loading…

None

New source string

FreeBSD Doc / books_developers-handbookEnglish

New source string 3 months ago
Browse all component changes

Things to check

Multiple failing checks

The translations in several languages have failing checks

Reset

Glossary

English English
No related strings found in the glossary.

Source information

Source string comment
(itstool) path: sect1/para
Labels
No labels currently set.
Flags
read-only
Source string location
book.translate.xml:10282
Source string age
3 months ago
Translation file
, string 1707