//----------------------------------------------------------------- // forkdemo.s // // This example reimplements our 'forkdemo.cpp' application // using GNU assembly language (instead of high-level C++). // // to assemble: $ as forkdemo.s -o forkdemo.o // and to link: $ ld forkdemo.o -o forkdemo // and execute: $ ./forkdemo // // QUESTION: Does this demo always work the way we expect? // // programmer: ALLAN CRUSE // written on: 04 MAR 2009 //----------------------------------------------------------------- # manifest constants .equ sys_fork, 57 # system-call ID-number .equ sys_getpid, 39 # system-call ID-number .equ sys_write, 1 # system-call ID-number .equ sys_exit, 60 # system-call ID-number .equ dev_stdout, 1 # device-file ID-number .section .data msg: .ascii "Hello from process #" # legend for the report buf: .ascii " \n" # buffer for PID string len: .quad . - msg # length of the message .section .text _start: # ask the kernel to fork a child-process mov $sys_fork, %rax # system-call ID-number syscall # invoke kernel service # ask the kernel for this process's PID mov $sys_getpid, %rax # system-call ID-number syscall # invoke kernel service # convert PID to a string of numerals lea buf, %rdi # point to buffer area call itoa # convert int to string # display the message mov $sys_write, %rax # system-call ID-number mov $dev_stdout, %rdi # device-file ID-number lea msg, %rsi # address of the message mov len, %rdx # length of the message syscall # invoke kernel service # terminate this application mov $sys_exit, %rax # system-call ID-number mov $0, %rdi # use zero as exit-code syscall # invoke kernel service .global _start # make entry-point public itoa: # converts RAX to a decimal digiot-string at EDI push %rax # save caller's registers push %rbx push %rcx push %rdx push %rdi mov $10, %rbx # decimal-system's radix xor %rcx, %rcx # initialize digit-count nxdiv: xor %rdx, %rdx # extend RAX to (RDX,RAX) div %rbx # divide (RDX,RAX) by ten push %rdx # push remainder onto stack inc %rcx # and count this remainder or %rax, %rax # was the quotient zero? jnz nxdiv # no, then divide again nxdgt: pop %rdx # recover prior remainder add $'0', %dl # convert number to ascii mov %dl, (%rdi) # store numeral in buffer inc %rdi # advance buffer pointer loop nxdgt # again for next remainder pop %rdi # restore saved registers pop %rdx pop %rcx pop %rbx pop %rax ret # return control to caller .end # nothing more to assemble