Browse Source

Add pwd program

Matteo Savatteri 4 years ago
parent
commit
2a8b764fce
2 changed files with 92 additions and 0 deletions
  1. 29 0
      2_pwd/Makefile
  2. 63 0
      2_pwd/src/pwd.s

+ 29 - 0
2_pwd/Makefile

@@ -0,0 +1,29 @@
+MAIN=pwd
+
+AS=as
+ASFLAGS=
+LD=ld
+LDFLAGS=
+
+SDIR=src
+ODIR=obj
+BDIR=bin
+
+
+$(BDIR)/$(MAIN): $(ODIR)/$(MAIN).o $(BDIR)
+	$(LD) -o $@ $(ODIR)/$(MAIN).o $(LDFLAGS)
+$(BDIR):
+	mkdir $(BDIR)
+
+$(ODIR)/$(MAIN).o: $(SDIR)/$(MAIN).s $(ODIR)
+	$(AS) -o $@ $(SDIR)/$(MAIN).s $(ASFLAGS)
+$(ODIR):
+	mkdir $(ODIR)
+
+
+.PHONY: clean clen-all
+
+clean:
+	rm -rf $(ODIR)
+clean-all:
+	rm -rf $(ODIR) $(BDIR)

+ 63 - 0
2_pwd/src/pwd.s

@@ -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