Skip to content

Instantly share code, notes, and snippets.

@bogen85

bogen85/hello1.c Secret

Last active August 8, 2020 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bogen85/4e24f5e6d1b8ad3ea2ec97af4f2d3172 to your computer and use it in GitHub Desktop.
Save bogen85/4e24f5e6d1b8ad3ea2ec97af4f2d3172 to your computer and use it in GitHub Desktop.
How does one reference literal strings from other units in free pascal in inline assembler?

This is just an prototype to see what is needed to target embedded systems.

The C one is for reference, to demonstrate the functionaly I'm looking for in pascal.

The pascal one builds and runs fine, however, getting the literal greeting as a problem. I'd like to pull that (and the size if need be) from another unit.

I don't mind linking with fpc, but size needs to be small.

$ make run
[hello]
copy from `hello' [elf64-x86-64] to `sty0OJET' [elf64-x86-64]
copy from `hello' [elf64-x86-64] to `sti0M0x0' [elf64-x86-64]
copy from `hello' [elf64-x86-64] to `stOZgE32' [elf64-x86-64]
copy from `hello' [elf64-x86-64] to `stWp5HC7' [elf64-x86-64]
strip: hello: warning: empty loadable segment detected at vaddr=0x400000, is this intentional?
copy from `hello' [elf64-x86-64] to `st4vv9df' [elf64-x86-64]
8544	hello
[run]
Hello world with C on Linux x86_64!

The pascal one is slightly smaller.

$ make linkpas 
[linkpas]
copy from `linkpas' [elf64-x86-64] to `stStyVSM' [elf64-x86-64]
copy from `linkpas' [elf64-x86-64] to `stTcQJ0R' [elf64-x86-64]
copy from `linkpas' [elf64-x86-64] to `st1xBmVW' [elf64-x86-64]
copy from `linkpas' [elf64-x86-64] to `stEYAJa0' [elf64-x86-64]
strip: linkpas: warning: empty loadable segment detected at vaddr=0x400000, is this intentional?
copy from `linkpas' [elf64-x86-64] to `stqa4GU4' [elf64-x86-64]
4440	linkpas
Sat 08Aug20 05:59:14 ~/never-lang-dev/scratch/pascal/ok/asm/c-lang
$ ./linkpas 
Hello, world!
// program hello1;
// uses hello2;
extern const char message[]; // (From hello2)
extern const int msglen;
// procedure greet;what here?;
// begin
// What here?
// end;
static void __attribute__((used,naked)) greet() { __asm__ (
"mov $1, %rax;" // write(
"mov $1, %rdi;" // STDOUT_FILENO,
"mov $message, %rsi;" // message,
"mov (msglen), %rdx;" // msglen
"syscall;" // );
"ret;");
}
// procedure done;what here?;
// begin
// What here?
// end;
static void __attribute__((used,naked)) done() { __asm__ (
"mov $60, %rax;" // exit (
"xor %rdi, %rdi;" // EXIT_SUCCESS
"syscall;"); // );
}
// begin
// greet;
// done;
// end.
void __attribute__((naked)) _start() {
greet();
return done();
}
unit hello1;
interface procedure _start;cdecl;
implementation
uses hello2;
{$goto on}
{$macro on}
{$asmmode intel}
procedure done;assembler;noreturn;nostackframe;
asm
mov rax, 60
xor rdi, rdi
syscall
end;
procedure message;assembler;noreturn;nostackframe;
asm
db "Hello, world!", 10
end;
procedure message_end;assembler;noreturn;nostackframe;
asm
end;
procedure greet;assembler;noreturn;nostackframe;
asm
mov rax, 1 // write(
mov rdi, 1 // STDOUT_FILENO,
mov rsi, message
mov rdx, message_end
sub rdx, rsi
sub rdx, 2
syscall // );
ret
end;
procedure _start;cdecl;export;[public name '_start'];noreturn;
begin
greet;
done;
end;
begin
end.
/*
unit hello2;
interface
const
message = 'Hello world with FPC on Linux x86_64!'#10;
msglen = ???
implementation
end.
*/
#define MESSAGE "Hello world with C on Linux x86_64!\n"
const char message[] = MESSAGE;
const int msglen = sizeof(MESSAGE)-1;
unit hello2;
interface
const greeting = 'What';
implementation
end.
# We are not using any builtins
MAKEFLAGS:= --warn-undefined-variables \
--no-builtin-rules \
--no-builtin-variables \
--output-sync=target \
--silent
.ONESHELL:
SHELL := bash
_ = set -euo pipefail ; echo '[$@]'
default:
$_
CFLAGS := -fno-stack-protector -ffunction-sections -fdata-sections
CFLAGS += -static -Os -fno-exceptions -nostartfiles -nostdlib
SECTIONS := .note.gnu.property .comment .eh_frame .note.gnu.build-id
CSRCS := $(shell find . -name '*.c')
EXE := hello
${EXE}: ${CSRCS} makefile
$_
gcc -o $@ ${CSRCS} ${CFLAGS}
strip --strip-all $@
for section in ${SECTIONS}; do
strip -v --remove-section=$$section $@
done
strip -v -x -X $@
du -b $@
clean:
$_
rm -vf ${EXE}
build: ${EXE}
run: ${EXE}
$_
./${EXE}
buildpas:
$_
rm -rf ./x
mkdir ./x
fpc -FE./x hello1.pas -s
linkpas: ./x/hello1.o
$_
gcc -o $@ $< ${CFLAGS}
strip --strip-all $@
for section in ${SECTIONS}; do
strip -v --remove-section=$$section $@
done
strip -v -x -X $@
du -b $@
@bogen85
Copy link
Author

bogen85 commented Aug 8, 2020

I would like to get fpc_shortstr_to_shortstr

[linkpas]
/usr/bin/ld: x/hello1.o: in function `HELLO1_$$_init$':
hello1.pas:(.text.n_hello1_$$_init$+0x26): undefined reference to `fpc_shortstr_to_shortstr'
collect2: error: ld returned 1 exit status
make: *** [makefile:51: linkpas] Error 1

As I'd like to able to use:

var msg:string;
begin
    msg := greeting; // where greeting is in another module, and would allow me to use msg in assembler
end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment