HelloWorld in assembly on riscv64 runs fine with debugging info; seg fault w/o debugging info
by tommylovell from LinuxQuestions.org on (#6QNBB)
I have a simple HelloWorld.s program that runs fine if debugging info included, but Seg Faults if no debugging.
The systems is a Mars, but this also happens on a StarFive Vision2. Both run Debian from their sites. I've made no modifications.
Here is the source code:
Code:user@mars1:~/source/HelloWorld_RSV$ cat HelloWorld.s
.EQU vers, "1.00"
#
# Risc-V Assembler program to print "Hello RISC-V World!"
# to stdout.
#
# a0-a2 - parameters to linux function services
# a7 - linux function number
#
.EQU stdout, 1
.include "/usr/local/asm/include/unistd.s"
.text
.global _start # Provide program starting address to linker
# Setup the parameters to print hello world
# and then call Linux kernel to do it.
_start: addi a0, x0, stdout # 1 = stdout
la a1, h # load address of helloworld
# addi a2, x0, 14 # what a crappy assembler...
la a2, l
lw a2, 0(a2) # l' of our string
addi a7, x0, sys_write # linux write system call
ecall # Call linux to output the string
# Setup the parameters to exit the program
# and then call Linux to do it.
addi a0, x0, 0 # Use 0 return code
addi a7, x0, sys_exit # service command code 93 terminates
ecall # Call linux to terminate the program
.data
h: .asciz "Hello World!!\n"
e:
l: .word e-h
user@mars1:~/source/HelloWorld_RSV$Here is the Makefile:
Code:user@mars1:~/source/HelloWorld_RSV$ cat Makefile
TEMPFILES = *.o *.out
PROGS = HelloWorld
ifdef DEBUG
DEBUGFLGS = -g
else
DEBUGFLGS =
endif
# %.s is like a wildcard, meaning any .s file.
# $< is a symbol for the source file.
# $@ is a symbol for the output file.
%.o : %.s
as $(DEBUGFLGS) -alh $< -o $@ > ${PROGS}.l
${PROGS} : ${PROGS}.o
ld -o ${PROGS} ${PROGS}.o
if [ ! -e ~/bin ]; then mkdir ~/bin/; fi
sudo mv ${PROGS} ~/bin/${PROGS}
.PHONY: clean
clean:
-rm -f ${PROGS} ${TEMPFILES}
-rm -f ~/bin/${PROGS}
user@mars1:~/source/HelloWorld_RSV$ make DEBUG=1 -BHere are the makes and executions:
Code:user@mars1:~/source/HelloWorld_RSV$ make DEBUG=1 -B
as -g -alh HelloWorld.s -o HelloWorld.o > HelloWorld.l
ld -o HelloWorld HelloWorld.o
if [ ! -e ~/bin ]; then mkdir ~/bin/; fi
sudo mv HelloWorld ~/bin/HelloWorld
user@mars1:~/source/HelloWorld_RSV$ ~/bin/HelloWorld
Hello World!!
user@mars1:~/source/HelloWorld_RSV$ make DEBUG= -B
as -alh HelloWorld.s -o HelloWorld.o > HelloWorld.l
ld -o HelloWorld HelloWorld.o
if [ ! -e ~/bin ]; then mkdir ~/bin/; fi
sudo mv HelloWorld ~/bin/HelloWorld
user@mars1:~/source/HelloWorld_RSV$ ~/bin/HelloWorld
Segmentation fault
user@mars1:~/source/HelloWorld_RSV$The segfault is in the 'sys_write'. If I use 'addi a2, x0, 14' instead of 'la a2, l' and 'lw a2, 0(a2)' it runs fine. Unfortunately there doesn't seem to be a way to find the length of a constant at assembly time, so I'm trying to do it at runtime.
Am I running into a 64-bit / 32-bit issue? Probably, but I'm a novice. Bug? I doubt it. I'm stumped.
[rant] Even back in 1970, the mainframe assembler was better than GAS. Just MHO. [/rant]
TIA
The systems is a Mars, but this also happens on a StarFive Vision2. Both run Debian from their sites. I've made no modifications.
Here is the source code:
Code:user@mars1:~/source/HelloWorld_RSV$ cat HelloWorld.s
.EQU vers, "1.00"
#
# Risc-V Assembler program to print "Hello RISC-V World!"
# to stdout.
#
# a0-a2 - parameters to linux function services
# a7 - linux function number
#
.EQU stdout, 1
.include "/usr/local/asm/include/unistd.s"
.text
.global _start # Provide program starting address to linker
# Setup the parameters to print hello world
# and then call Linux kernel to do it.
_start: addi a0, x0, stdout # 1 = stdout
la a1, h # load address of helloworld
# addi a2, x0, 14 # what a crappy assembler...
la a2, l
lw a2, 0(a2) # l' of our string
addi a7, x0, sys_write # linux write system call
ecall # Call linux to output the string
# Setup the parameters to exit the program
# and then call Linux to do it.
addi a0, x0, 0 # Use 0 return code
addi a7, x0, sys_exit # service command code 93 terminates
ecall # Call linux to terminate the program
.data
h: .asciz "Hello World!!\n"
e:
l: .word e-h
user@mars1:~/source/HelloWorld_RSV$Here is the Makefile:
Code:user@mars1:~/source/HelloWorld_RSV$ cat Makefile
TEMPFILES = *.o *.out
PROGS = HelloWorld
ifdef DEBUG
DEBUGFLGS = -g
else
DEBUGFLGS =
endif
# %.s is like a wildcard, meaning any .s file.
# $< is a symbol for the source file.
# $@ is a symbol for the output file.
%.o : %.s
as $(DEBUGFLGS) -alh $< -o $@ > ${PROGS}.l
${PROGS} : ${PROGS}.o
ld -o ${PROGS} ${PROGS}.o
if [ ! -e ~/bin ]; then mkdir ~/bin/; fi
sudo mv ${PROGS} ~/bin/${PROGS}
.PHONY: clean
clean:
-rm -f ${PROGS} ${TEMPFILES}
-rm -f ~/bin/${PROGS}
user@mars1:~/source/HelloWorld_RSV$ make DEBUG=1 -BHere are the makes and executions:
Code:user@mars1:~/source/HelloWorld_RSV$ make DEBUG=1 -B
as -g -alh HelloWorld.s -o HelloWorld.o > HelloWorld.l
ld -o HelloWorld HelloWorld.o
if [ ! -e ~/bin ]; then mkdir ~/bin/; fi
sudo mv HelloWorld ~/bin/HelloWorld
user@mars1:~/source/HelloWorld_RSV$ ~/bin/HelloWorld
Hello World!!
user@mars1:~/source/HelloWorld_RSV$ make DEBUG= -B
as -alh HelloWorld.s -o HelloWorld.o > HelloWorld.l
ld -o HelloWorld HelloWorld.o
if [ ! -e ~/bin ]; then mkdir ~/bin/; fi
sudo mv HelloWorld ~/bin/HelloWorld
user@mars1:~/source/HelloWorld_RSV$ ~/bin/HelloWorld
Segmentation fault
user@mars1:~/source/HelloWorld_RSV$The segfault is in the 'sys_write'. If I use 'addi a2, x0, 14' instead of 'la a2, l' and 'lw a2, 0(a2)' it runs fine. Unfortunately there doesn't seem to be a way to find the length of a constant at assembly time, so I'm trying to do it at runtime.
Am I running into a 64-bit / 32-bit issue? Probably, but I'm a novice. Bug? I doubt it. I'm stumped.
[rant] Even back in 1970, the mainframe assembler was better than GAS. Just MHO. [/rant]
TIA