Recent Posts

Pages: [1] 2 3 ... 10
1
Programming with NASM / Re: createProcessA win64
« Last post by Frank Kotler on November 23, 2021, 09:46:46 PM »
Hi Bgrim,

Welcome to the Forum.

I don't "do Windows". What I see missing is:
Code: [Select]
extern CreateProcessA
Probably want ExitProcess, too.
"shr edx, 8" looks suspicious, too.

Hope a Windows user can help you!

Best,
Frank

2
Programming with NASM / createProcessA win64
« Last post by Bgrim on November 23, 2021, 06:02:53 AM »
Hi.

I need help with CreateProcessA, it doesn't work and I don't know why...

I did this code first, but it doesn't work, someone explained me that maybe the parameters are corrupting ProcessInfo.

Code: [Select]
mov r13, rdx  ;CreateProcessA

xor rdx, rdx
xor r15, r15
mov edx, 0x646d6361
shr edx, 8
push rdx
mov r15, rsp    ;cmd

xor rdx, rdx
push rdi  ;socket
push rdi  ;socket
push rdi  ;socket
push rdx
push rdx
xor rax, rax
inc rax
rol rax, 8
push rax    ;0x00000100
push rdx
push rdx
push rdx
push rdx
push rdx
push rdx
push rdx
push rdx
push rdx
push rdx
xor rax, rax
add al, 44
push rax
xor r14, r14
mov r14, rsp ;STARTUPINFOA

xor r12, r12
sub rsp, 0x16
mov r12, rsp  ;ProcessInfo

sub rsp, 0x58 ;shadowspace

mov [rsp+72], r12 ;ProcessInfo
mov [rsp+64], r14 ;STARTUPINFOA
mov [rsp+56], rdx
mov [rsp+48], rdx
mov [rsp+40], rdx
xor rax, rax
inc rax
mov [rsp+32], rax
xor r8, r8
xor r9, r9
mov rdx, r15  ;cmd
xor rcx, rcx

call r13

well, so I change the code and I did this.

Code: [Select]
mov r13, rdx ;CreateProcessA

xor rdx, rdx
xor r15, r15
mov edx, 0x646d6361
shr edx, 8
push rdx
mov r15, rsp    ;cmd

xor r12, r12
xor rcx, rcx
xor rdx, rdx
mov rcx, 0x80

lop_nul:
push rdx
loop lop_nul  ;space for STARTUPINFOA and ProcessInfo

xor rax, rax
mov al, 0x68

lea r12, [rsp]
mov [r12], dword eax
mov [r12+4], rcx
mov [r12+12], rcx
mov [r12+20], rcx
mov [r12+24], rcx

xor rdx, rdx
mov dl, 255
inc rdx

mov [r12+0x3c], edx ;0x00000100
mov [r12+0x50], rdi ;socket
mov [r12+0x58], rdi ;socket
mov [r12+0x60], rdi ;socket


xor rdx, rdx

sub rsp, 0x58

lea r9, [r12]
mov [rsp+64], r9
lea r9, [r12+104]
mov [rsp+72], r9
mov [rsp+56], rdx
mov [rsp+48], rdx
mov [rsp+40], rdx
xor rax, rax
inc rax
mov [rsp+32], rax
xor r8, r8
xor r9, r9
mov rdx, r15  ;cmd
xor rcx, rcx

call r13

With a source code on C++ using CreateProcess and debugging the code I don't see the real problem.

So, can somebody help me with this please?.
3
Using NASM / Re: LEA or MOV
« Last post by munair on November 17, 2021, 01:31:38 PM »
When I get to optimization options for the compiler, fomitting the frame pointer will probably be one of them. Thanks again for the suggestion.
4
Using NASM / Re: LEA or MOV
« Last post by fredericopissarra on November 17, 2021, 12:23:22 PM »
What is the difference between the struct approach and the stack frame approach other than keeping R/EBP free? Maybe I misunderstand. I have seen examples of GCC (32bits) output producing stack frames, so it still seems a legitimate technique.

Smaller and fastest code. Try to use -fomit-frame-pointer and -O2 options on GCC...

Quote
When you say Pascal compiler, which compiler do you mean? There are several of them, both commercial and free. Same goes for C compilers.
Turbo Pascal, Free Pascal and Delphi... And the old "pascal" calling convention used by C compilers back in the 90's, 2000's: Turbo C, Borland C++, MSC6, ...
5
Using NASM / Re: LEA or MOV
« Last post by munair on November 17, 2021, 11:42:14 AM »
What is the difference between the struct approach and the stack frame approach other than keeping R/EBP free? Maybe I misunderstand. I have seen examples of GCC (32bits) output producing stack frames, so it still seems a legitimate technique.

Currently in the SharpBASIC compiler the stack cleanup is done after the function call, as it was also messed up with the push instructions before the call. Seems more logical to me, but it's a matter of opinion. Here is a simple, stupid example I used to test function calls in the expression parser:

Code: [Select]
' SharpBASIC function
' -------------------
incl "lib/sys.sbi";

decl func five(n: int8): int8;

dim sum: int8;

main do
  sum = five(5 * 5) + five(5 + 5);
  print sum;
end;

func five(n: int8): int8
do
  five = n;
end;

Generated asm code (without any code optimizations):

Code: [Select]

SECTION .text

global  _start
global  _end

_start:
movsx   eax, byte [_C3]
push    eax
movsx   eax, byte [_C3]
pop     edx
imul    edx
push    eax

call    _I26

add     esp, 4
push    eax
movsx   eax, byte [_C3]
push    eax
movsx   eax, byte [_C3]
pop     edx
add     eax, edx
push    eax

call    _I26

add     esp, 4
pop     edx
add     eax, edx
; save sum
mov     [_I27], al
; load sum
movsx   eax, byte [_I27]
; print int
mov     ebx, _sb_buf12
call    _sb_intstr
call    _sb_print
call    _sb_printlf

_end:
mov     ebx, 0
mov     eax, 1
int     80h

_I26:
push    ebp
mov     ebp, esp
sub     esp, 4
; init func five
mov     byte [ebp - 4], 0
; load n
movsx   eax, byte [ebp + 8]
; save func result five
mov     [ebp - 4], al
._L0:
; load func result five
movsx   eax, byte [ebp - 4]
mov     esp, ebp
pop     ebp
ret

extern  _sb_intstr
extern  _sb_print
extern  _sb_printlf
extern  _sb_buf12

SECTION .rodata

_C3                 db 5

SECTION .bss

; define sum
_I27                resb 1

When you say Pascal compiler, which compiler do you mean? There are several of them, both commercial and free. Same goes for C compilers.
6
Using NASM / Re: LEA or MOV
« Last post by fredericopissarra on November 17, 2021, 10:36:35 AM »
I think it is not a good idea for the simple reason that the stack pointer may change during the execution of a function. Suppose the code within a function calls another function and (local) variables are pushed on the stack to pass them as parameters. How do you access local variables after the stack pointer has changed?

That's why compilers like C keeps track of (E|R)SP... Supose you have a funcion f() calling a function g(), each one with one argument, using i386 C callng convention:
Code: [Select]
int g(int x) { return x + x; }
int f(int x) { return g(x)+1; }
The generated code is something like this (without using EBP):
Code: [Select]
g:
  mov eax,[esp+4]
  add  eax,eax
  ret

f:
  mov eax,[esp+4]
  push eax
  call g
  add esp,4  ; stack cleanup. keeps in a known position.
  inc eax
  ret

Using the struct approach you'll always sure where arguments and local vars are for a function and don't need to remember the offsets. All you have to do is to pop the pushed argumentos from the stack after the function returns (or before...).

In some compilers (PASCAL, for instance) the responsability for stack cleanup is on the called function ("ret" accepts an argument for that)... The same come, in pascal:
Code: [Select]
g:
  mov eax,[esp+4]
  add  eax,eax
  ret 4

f:
  mov eax,[esp+4]
  push eax
  call g
  inc eax
  ret 4

The point is: Why use prologue/epilogue nowadays? In the old pre-386 processors if you wanted to access data on stack you had two options only: Using POP and using EBP as base pointer in an effective address. It was not possible to use registers other than BP ou BX as base pointer, and other registers than SI or DI as index (and there were no 'scale'), so using BP was mandatory. After 386 this is not the case anymore.
7
Using NASM / Re: LEA or MOV
« Last post by munair on November 17, 2021, 09:11:34 AM »
Did you notice using a structure you don't need to remember where is the arguments or local stack allocated objects?

It's not to remember but to make life simple. Giving your proposal of using the stack pointer without stack frame some thought, I think it is not a good idea for the simple reason that the stack pointer may change during the execution of a function. Suppose the code within a function calls another function and (local) variables are pushed on the stack to pass them as parameters. How do you access local variables after the stack pointer has changed? This is where the base pointer comes in. No matter what happens to the stack pointer, the base pointer makes sure that the offsets to local variables and parameters don't change.
8
Using NASM / Re: LEA or MOV
« Last post by fredericopissarra on November 16, 2021, 09:14:21 PM »
Did you notice using a structure you don't need to remember where is the arguments or local stack allocated objects?
9
Using NASM / Re: Parse string to segments
« Last post by munair on November 15, 2021, 10:15:55 PM »
I'm happy that 'extract' works. I will use it as example for string manipulation routines in the SharpBASIC compiler.
10
Using NASM / Re: Parse string to segments
« Last post by munair on November 15, 2021, 10:12:42 PM »
I compile 32bits code with NASM and LD on Manjaro Linux x64. The code for the SharpBASIC 32bits compiler I work on (not to confuse with the BASIC referred to by the OP) compiles and runs fine. But Frank's example doesn't. I'm sure it's because of ld-linux.so.2, which I don't use for my code.
The question is there because of this error:
Code: [Select]
[frank@frank-pc xmpl]$ ld -o extract extract.o -I/lib/ld-linux.so.2 -lc
ld: i386 architecture of input file `extract.o' is incompatible with i386:x86-64 output
You are trying to link an ELF32 object file to an ELF64 one. So, what is it? 64 or 32 bits?

The only object file is extract.o, which is 32 bits. I finally got it linked with:

Code: [Select]
ld -o extract extract.o -m elf_i386 -L /usr/lib32 -lc -dynamic-linker /lib/ld-linux.so.2

Without "-dynamic-linker" links too, but the resulting executable doesn't run. Although it's there, I get "no such file or directory".

Pages: [1] 2 3 ... 10