Recent Posts

Pages: [1] 2 3 ... 10
1
Programming with NASM / Re: how to print from array of strings? (openbsd)
« Last post by fredericopissarra on October 15, 2019, 12:41:02 AM »
Didn't test it with FreeBSD:
Code: [Select]
; test.asm
  bits 64
  default rel

  %define NULL 0

  section .rodata

msg1: db  `Message1\n\0`
msg2: db  `Message2\n\0`
msg3: db  `Message3\n\0`

msgs: dq  msg1, msg2, msg3, NULL

  section .text

  global _start
_start:
  lea   rbx,[msgs]      ; RBX is preserved between syscalls (SysV ABI).

.loop:
  mov   rdi,[rbx]       ; Get a pointer in msgs table.
  test  rdi,rdi         ; If it is NULL...
  jz    .exit_loop      ; ... exit loop.

  call  strlen          ; Return the string length in RDX.

  mov   rsi,[rbx]       ; Get the pointer again...
  mov   eax,1           ; write_syscall
  mov   edi,eax         ; to STDOUT
  syscall

  add   rbx,8           ; Next pointer in msgs table.
  jmp   .loop
.exit_loop:

  xor   edi,edi         ; Return value is 0 (EXIT_SUCCESS).
  mov   eax,60          ; exit_syscall
  syscall
 
; Obs: We won't use strings greater than 4 GiB, so it is safe to use EDX.
strlen:
  xor   edx,edx
.loop:
  cmp   byte [rdi+rdx],0
  jz    .exit_loop
  add   edx,1
  jmp   .loop
.exit_loop:
  ret

Code: [Select]
# Makefile

test: test.o
ld -o $@ $^

test.o: test.asm
nasm -felf64 -o $@ $<
2
Programming with NASM / Re: how to print from array of strings? (openbsd)
« Last post by mmk213 on October 14, 2019, 09:44:33 PM »
Just to illustrate what was my problem. It was this:
Code: [Select]
rax = 0000027574101000 rbx = 0000000000000000
rcx = 0000000000000000 rdx = 0000000000000000
rdi = 0000000000000000 rsi = 0000000000000000
rsp = 00007f7ffffd79a0 rbp = 0000000000000000
r8  = 000002757410101c r9  = 000000000020101c
r10 = 000002757410102e r11 = 000000000020102e
r12 = 000002757410103d r13 = 000000000020103d
r14 = 000002757410105d r15 = 000000000020105d
So in this regdump, r8 is address of message_one, which I obtained by:
Code: [Select]
lea r8, [rel message_one]
and r9 is the value of first quad in message_array:
Code: [Select]
message_array:
dq message_one
dq message_two
dq message_three
So, those two values are NOT the same.
But the same code (with different syscall numbers of course) on linux gives the "right" result: r8 and r9 are the same.
It is like that value of message_one in message_array did not get "relocated". I dont know.
I know how to manually solve it - but I think surely this is a linker problem or something.
3
Programming with NASM / Re: how to print from array of strings? (openbsd)
« Last post by mmk213 on October 14, 2019, 09:24:06 PM »
Nevermind. I'll do the manual thing so that it works.. thanks.
4
Programming with NASM / Re: how to print from array of strings? (openbsd)
« Last post by mmk213 on October 14, 2019, 09:16:17 PM »
"Surely you want 1 in rax. If that's not a "posto", it's your problem."

oh dear god.
it is an example.
a minimal working example.

i put zero just to show that rax is an index to an array.
of course it is not a mistake.
that is not my problem. i already wrote what the problem is but reading is hard, i guess.

i know how to solve my problem - i can do some sort of "manual relocation" on that array so the code would work.
but i'm guessing there is a more straighforward way to do it via linker or something.
5
Programming with NASM / Re: how to print from array of strings? (openbsd)
« Last post by Frank Kotler on October 14, 2019, 09:06:11 PM »
Code: [Select]
  ; ok, now lets print message from array
  ; lets use rax as an index of array
  mov rax, 0
  shl rax, 3        ; pointers are 8 bytes long
 

Surely you want 1 in rax. If that's not a "posto", it's your problem.

Best,
Frank

6
Programming with NASM / Re: how to print from array of strings? (openbsd)
« Last post by mmk213 on October 14, 2019, 11:56:32 AM »
oh, I should mention that this above example works of course in linux 64 bit no problem.
7
Programming with NASM / how to print from array of strings? (openbsd)
« Last post by mmk213 on October 14, 2019, 11:52:23 AM »
This is my minimal code example.
I am trying to basically print one string from array of strings.
And I think relocation destroys me here.
This is my example, sorry about formatting, I am typing this by hand:

Code: [Select]
  global start
  sys_exit equ 0x01
  sys_write equ 0x04
  stdout equ 0x01
  %define sys syscall

  section .text

start:
  ; ok lets print one message, it works of course
  lea rdi, [rel message_one]
  call print_c

  ; ok, now lets print message from array
  ; lets use rax as an index of array
  mov rax, 0
  shl rax, 3        ; pointers are 8 bytes long
  lea rdi, [rel message_array]
  add rdi, rax
  mov rdi, [rdi]
  call print_c

  mov rax, sys_exit
  sub rdi, rdi
  sys

print_c:
  push rax
  push rcx
  push rdx
  push rdi
  push rsi
  push r11
  cld
  sub ecx, ecx
  push rdi
  dec rcx
  sub eax, eax
  repnz scasb
  pop rsi
  mov rdx, rcx
  add al, sys_write
  not rdx
  sub edi, edi
  dec rdx
  inc edi
  sys
  pop r11
  pop rsi
  pop rdi
  pop rdx
  pop rcx
  pop rax
  ret

  section .data

message_one:
  db 'This is the first message.', 0x0a, 0x00

message_two:
  db 'This is the second message.', 0x0a, 0x00

message_three:
  db 'This is the third message.', 0x0a, 0x00

message_array:
  dq message_one
  dq message_two
  dq message_three

  section .note.openbsd.ident
  align 2
  dd 8, 4, 1
  db 'OpenBSD', 0
  dd 0
  align 2

build
Code: [Select]
nasm -o example.o -f elf64 example.s
ld.bfd -e example -e start -static example.o

This segfaults of course, the wrong address is put in rdi at the end of second print example.

How to do this correctly? What am I missing?
Sorry about typos if there are some, I typed it by hand, but the example is simple enough.

Thanks.
8
Programming with NASM / Re: Why do MUL and IMUL give the same output?
« Last post by fredericopissarra on October 14, 2019, 03:18:24 AM »
Ok, just tested my theory and IMUL did NOT output 0xFFFF8000 as I thought it would. Seems strange.
However, it DID trigger the overflow and carry flags.
Consider IMUL with 2 "positive" maximum values: 0x7fff * 0x7fff. This will result in 0x3fff0001, still a "positive" 32 bits value.
9
Programming with NASM / Re: Why do MUL and IMUL give the same output?
« Last post by ben321 on October 14, 2019, 02:19:45 AM »
You are forgetting that MUL/IMUL results, in this case, are 32 bits values stored in DX:AX.
Using IMUL, 0x4000 times 2 is 0x00008000 (32 bits).!

Good point, but one error. The output may occupy 32bits, but I think the range of possible output values is still the range allowed for 16bit signed integers. Therefore, your statement that the output of IMUL for 0x4000 and 2, would actually be 0xFFFF8000 (not 0x00008000 like you said). That is, it outputs a 32bit signed value which represents the corresponding 16bit signed output of the IMUL operation. In order to do this, if the value represented by 16bits is negative, the 32bit value is simply sign-extends the top bit of the 16bit value to the upper 16bits of the 32bit value. This must happen with signed 16bit value 0x8000, because positive 0x8000 is not a valid 16bit signed integer, and therefore clearly is represents a negative number. And when generating negative 16bit signed integer 0x8000 from positive numbers 0x4000 and 2, there must clearly be an overflow happening.

Ok, just tested my theory and IMUL did NOT output 0xFFFF8000 as I thought it would. Seems strange.
However, it DID trigger the overflow and carry flags.
10
Programming with NASM / Re: Why do MUL and IMUL give the same output?
« Last post by fredericopissarra on October 13, 2019, 10:58:53 AM »
I still get the same output value of 0x8000 stored in AX. However, this is invalid, since both inputs are positive, and therefore the output is clearly also positive, but positive 0x8000 is an INVALID value for a 16bit signed integer. Why does the CPU actually complete this calculation, instead of throwing an error (which then would need to be handled by SEH, structured exception handling, in the program)?

It seems that with the CPU ignoring this error condition, MUL and IMUL operators are actually identical.
You are forgetting that MUL/IMUL results, in this case, are 32 bits values stored in DX:AX.
Using IMUL, 0x4000 times 2 is 0x00008000 (32 bits).

MUL/IMUL doesn't raise exceptions, they affect the flags (CF and OF - they have the same meaning: flagging overflow condition). Here's a simple test:
Code: [Select]
; mul.asm
bits  64

section .text

; int testmul( int *carry );
  global testmul
testmul:
  mov ecx,0x40000000
  mov eax,2
  imul ecx
  mov ecx,0
  setc cl
  mov [rdi],ecx
  ret
Code: [Select]
/* test.c */
#include <stdio.h>

extern int testmul( int * );

int main( void )
{
  int r, c;

  r = testmul(&c);

  printf( "result=%#x, carry=%d\n", r, c );
}
This will result in:
Code: [Select]
result=0x80000000, carry=1As it should!
Pages: [1] 2 3 ... 10