|
@@ -0,0 +1,63 @@
|
|
|
+.text # Section for machine istructions to be executed
|
|
|
+ .global _start # Needed by ld to find his default entry point
|
|
|
+_start: # _start symbol
|
|
|
+ mov $79, %rax # Put "79" in %rax register. 79 = sys_getcwd call
|
|
|
+ mov $buf, %rdi # Put the starting address of the buffer 'buf'
|
|
|
+ # in %rdi register. This syscall expect this buffer
|
|
|
+ # to write into the path of che cwd
|
|
|
+ mov $4096, %rsi # Put in %rsi register the length of 'buf' buffer.
|
|
|
+ # Is 4096 byte enough? It would be better to use
|
|
|
+ # MAX_PATH
|
|
|
+ syscall # Ask Linux to perform syscall indexed by %rax
|
|
|
+
|
|
|
+ movb $0x0A, -1(%rdi,%rax) # A pro gamer move: substitute the trailing 0 char
|
|
|
+ # of the string written in 'buf' by the kernel
|
|
|
+ # sys_getcwd routine, with '\n':
|
|
|
+ # * 0x0A is hex for '\n'
|
|
|
+ # * After sys_getcwd %rax contains the length of the
|
|
|
+ # buffer filled (which includes the ending '\0'
|
|
|
+ # character)
|
|
|
+ # * Addressing mode:
|
|
|
+ # displacement(base,index,scale) =
|
|
|
+ # base + index*scale + diplacement
|
|
|
+ # +base = %rdi = contains address of 'buf'
|
|
|
+ # +index = %rax = contains the # of bytes to walk
|
|
|
+ # after base address to find the desired spot
|
|
|
+ # in memory: the end of the space filled by getcwd
|
|
|
+ # in 'buf'
|
|
|
+ # +displacement = -1 = like index but fixed integer
|
|
|
+ # in code: -1 to point to the last char in 'buf'
|
|
|
+ # +scale = 1 = multiplier for index
|
|
|
+ # * b in movb: specify that the value to be placed in
|
|
|
+ # memory has the length of a byte (ASCII char)
|
|
|
+
|
|
|
+ mov %rdi, %rsi # Put the starting address of the buffer 'buf'
|
|
|
+ # in %rsi register (this address was put in %rdi
|
|
|
+ # by a previous instruction and left unchanged by
|
|
|
+ # the kernel during the routine of the last syscall:
|
|
|
+ # this realization avoids the processor accessing
|
|
|
+ # memory to retrieve the desired address)
|
|
|
+ mov $1, %rdi # Put "1" in register %rdi. sys_write expects a
|
|
|
+ # file descriptor in this register. 1 = std out
|
|
|
+ mov %rax, %rdx # Put the number of byte to read from 'buf' and write
|
|
|
+ # to fd. See previous code block for the content
|
|
|
+ # of %rax at this point of the execution.
|
|
|
+ mov $1, %rax # Put "1" in %rax register. 1 = sys_write call
|
|
|
+ # NOTE: %rax was filled after the argument register %rdx
|
|
|
+ # for the convenience of "mov %rax, %rdx" (avoid
|
|
|
+ # access in memory)
|
|
|
+ syscall # Ask Linux to perform syscall indexed by %rax
|
|
|
+
|
|
|
+ mov $60, %rax # Put "60" in %rax register. 60 = sys_exit call
|
|
|
+ xor %rdi, %rdi # Set %rdi register to "0". %rdi = where to put
|
|
|
+ # exit status argument of sys_exit. Using the 'xor'
|
|
|
+ # istruction is an optimization: avoid retrieving "0"
|
|
|
+ # in memory)
|
|
|
+ syscall # Ask Linux to perform syscall indexed by %rax
|
|
|
+
|
|
|
+.section .bss # Assemble the following code into bss section
|
|
|
+ buf: # Define a symbol (tag) named 'buf' to identify
|
|
|
+ # the starting address of a buffer in code
|
|
|
+ .skip 4096 # Assemble a "space" of 4096 byte. This will be
|
|
|
+ # a buffer of 4096 zeroed byte in bss segment
|
|
|
+ # starting at address 'buf' during execution
|