ASM refresher

Associate
Joined
22 Sep 2009
Posts
2,085
Location
Leicester
I've started relearning ASM, I didn't realise just how much I'd forgotten over the years :p

Anyway, I'm using NASM and we'll assume x86 Linux for now, I remember some bits and pieces and I've managed to figure a few things out reading example code online, but there are a few things which I'm slightly confused about and was wondering if anyone could elaborate on what things were doing (if you can explain it in C terms that's even better)! My experience comes mainly from programming micro controllers so obviously there are bits and pieces which I've not needed in the past.

My first issue is working with variable strings, I can't remember if this is possible but typing all my strings in the data segment is getting tedious, can I move a string of letters into a resb 256 for example?

Basically this into ASM:
Code:
strcpy(string, "Hello World!");
for example.

Second is modifying individual bits, how would one go about it?

I'm aware I could probably figure these out using a disassembler, but would rather ask here.

There is more, however I'm hoping that I'll be able to figure that out myself I've got these 2 bases covered, if not I'll be posting back ;)
 
Well that depends on the CPU and the operating system.. I've done a fair amount in ARM, some in 68000 and some in BlackFin but none in intel :p
 
In x86, you can copy strings byte by byte (movsb or by word (movsw (2 bytes).

the movsb instruction will do it, so you load the src and destination address into registers then mini-loop moving bytes till completion.

Something like:
Code:
str2: resb 7
...
section .data
str1 db "Helloz", 0x0
...

mov esi, str1    ; put address of str1 into esi
mov edi, str2   ; put address of str2 into edi
cld
mov ecx, 7
rep movsb

As for modifying actual bits, I think it's just a case of loading up the relevant offset into a register, then doing the operation your after e.g

Code:
mov edi, [offset] 
XOR edi,edi ; bit operation

* may all be wrong, assembly coding causes mind corruption :p *
 
Last edited:
@NickK I did say x86 Linux, I thought it'd be pretty obviously Intel x86 Linux :rolleyes:

@tntcoder Thanks for that, I'll give it a shot. I vaguely remember doing a tad of ASM (for Windows) and using macros to copy strings, so now I'll look into doing that again.

Ok, written a macro following the NASM documentation (fantastic source of info).

Code:
%macro	STRING 1+
	jmp %%endstr
%%str:	db	%1
%%endstr:
	mov	edx,%%str					; move string address to dx
	mov	ecx,11						; length
	mov	ebx,1
	mov	eax,4						; sys_write
	int	0x20						; call kernel
%endmacro

segment .data

segment .bss

segment .text

	[GLOBAL str_asm]
	
	str_asm:
		
;		STRING "Hello World"
		
		mov	ebx,0					; exit number
		mov	eax,1					; sys_exit
		int	0x20					; call kernel

Now I assemble this, run it and segfault, even removing the macro completely has no effect. Assembles fine just won't run, strace has given me nothing useful to go on either.
 
Last edited:
What about alignment after the string (also does the string null terminate correctly?). Other than that all I can think about is possibly the return mechanism.
 
assuming by x86 you mean 32-bit, and not x86-64, where syscalls are an entirely different kettle of fish :

- swap ecx/edx in your STRING macro - ecx should be the address and edx the count.
- use int 0x80, not 0x20
- might want to add a ",10" after the string and output 12 bytes instead of 11 so you get a newline.

works after those changes :)
 
EDIT:
Ignore the below post, changing 0x20 to 0x80 worked, I have no clue how I got myself confused, my previous code to create files called 0x80 so I can't figure out where 0x20 came from...

Well if you notice I commented out that and as I say, I removed the macro completely and it still segfaults.

@matja I hadn't noticed the edx/ecx mixup so thanks for pointing that out. Trying to figure out where I plucked 0x20 from, my other test run of code used 0x80 so I'm confused how I made that mistake. And yes 32 bit, trying to keep it compatible with my other system.

For the record this is what I'm using to assemble/compile

Code:
nasm -f elf str.asm
gcc -o output str.o main.c

and main.c

Code:
int main(int argc, char **argv)
{
	int ret_status;
	ret_status = str_asm();
	return ret_status;
}

even using

Code:
segment .text

	[GLOBAL str_asm]
	
	str_asm:
		
;		STRING "Hello World"
		
		mov	ebx,0					; exit number
		mov	eax,1					; sys_exit
		int	0x20					; call kernel

segfaults, and I have no clue why.
 
Last edited:
Ahh that's different from straight assembler.

You linking in the C runtime by doing this. Usually if you're writing for inclusion with a C compiler as a function call you'll need to adhere to the compiler's framing and register convention. Seems odd you're jumping with a kernel sys_exit when returning as a called routine.
 
Last edited:
Back
Top Bottom