I am trying to understand how to use pointer in assembly. By reading some tutorials around internel,I think had undertantood some concepts. But when I'II go to try it,it did work. Below some attempts to translate C to ASM.
C
const char *s = "foo";
unsigned z = *(unsigned*)s;
if(!(z & 0xFF))
do_something();
if(!(z & 0xFFFF))
do_b_something();
(here's not full code,but it's a word-check,thefore,there is more two stmts which checks 0xFF0000,0xF000000 respectivily.
ASM:
mov ebp,str
mov eax,ebp
mov eax,[eax]
and eax,0xFF
cmp eax,0
je etc
mov eax,[eax]
and eax,0xFFFF
cmp eax,0
je etc
It returns a seg fault.
And the try:
mov eax,dword ptr [eax]
that's generated by gcc compiler and you can see it in some other assemblies code,returns
invalid symbol
on FASM assembler. It isn't really supported by the FASM or am I missing something?
I think this is what you are attempting to do:
mov ebp,str
mov eax,ebp
mov ebx,[eax]
test ebx,0xFF
jz low_byte_empty
do_something:
; some code here...
low_byte_empty:
test ebx,0xFFFF
jz low_word_empty
do_b_something:
; some code here.
low_word_empty:
Explanation:
First, as JasonD already mentions in his answer, you are loading a pointer to eax, then doing a logical and to it, then you are using the result still in eax to address memory (some memory offset in the range 0x0 ... 0xFF).
So what goes wrong in your code: you can't keep in the same register both a pointer to a memory address and a value at the same time. So I chose to load the value from [eax] to ebx, you can also use some other 32-bit general register (ecx, edx, esi, edi) according to your needs.
Then, you don't need to use cmp to check if a register is empty, because all cmp does is that it does the subtraction and sets the flags. But ZF (zero flag) is already set by and, so cmp is absolutely unnecessary here. Then, as cmp is not needed here and we do not need the result either, we only want to update the flags, it's better to use test. test does exactly the same logical AND as and does, the only difference being that test does not store the result, it only updates the flags.
It's not at all clear what you're trying to do in the original code - doesn't look right.
However this:
mov eax,[eax]
and eax,0xFF
cmp eax,0
je etc
mov eax,[eax]
Isn't going to work. You're overwriting the contents of EAX with the value stored at the address in EAX, manipulating that value, and then trying to reload it after the branch without restoring the original pointer.
Following variant is simpler, smaller, faster and uses only one register.
mov eax, str
mov eax,[eax]
test al, al
jz low_byte_empty
do_something_byte:
; some code here...
low_byte_empty:
test ah, ah
jz low_word_empty
do_something_word:
; some code here
low_word_empty:
Related
I'm trying to write a function in x86 NASM assembly which reverses order of characters in a string passed as argument. I tried implementing it using stack but ended up getting error message
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)
Code below:
section .text
global reverse
reverse:
push ebp ; epilogue
mov ebp, esp
mov eax, [ebp+8]
xor ecx, ecx ; ecx = 0
push ebx ; saved register
push_eax:
mov edx, [eax] ; edx = char at eax
test edx, edx
jz inc_eax ; if edx == 0, move eax pointer back and pop eax
push edx
inc eax
inc ecx ; counter + 1
jmp push_eax
inc_eax:
sub eax, ecx ; move eax back to beginning of string
mov ebx, ecx ; to move eax back at the end of function
pop_eax:
test ecx, ecx ; loop counter == 0
jz end
pop edx
mov [eax], edx ; char at eax = edx
inc eax ; eax++
dec ecx ; ecx--
jmp pop_eax
end:
sub eax, ebx
pop ebx ; saved register
mov esp, ebp
pop ebp
ret
C declaration:
extern char* reverse(char*);
I've read somewhere that you get this error when trying to for instance write something in an array that is longer than allocated but i don't see how would that function do it? Also when instead of using ebx at the end I manually move the pointer in eax back (string in C of length 9 -> sub eax, 9) I get the reversed string at the output followed by 2nd, 3rd and 4th char. (No matter the length of the string I declare in C). So for instanceinput: "123456789"
output: "987654321234" but that only happens when I move eax manually, using ebx like in the code above outputs some trash.
Peter's answer is the answer you are looking for. However, may I comment on the technique? Must you use the stack? Do you already know the length of the string, or must you calculate/find that yourself?
For example, if you already know the length of the string, can you place a pointer at the first and another at the end and simply exchange the characters, moving each pointer toward the center until they meet? This has the advantage of not assuming there is enough room on the stack for the string. In fact, you don't even touch the stack except for the prologue and epilogue. (Please note you comment that the epilogue is at the top, when it is an 'ending' term.)
If you do not know the length of the string, to use the above technique, you must find the null char first. By doing this, you have touched each character in the string already, before you even start. Advantage, it is now loaded in to the cache. Disadvantage, you must touch each character again, in essence, reading the string twice. However, since you are using assembly, a repeated scasb instruction is fairly fast and has the added advantage of auto-magically placing a pointer near the end of the string for you.
I am not expecting an answer by asking these questions. I am simply suggesting a different technique based on certain criteria of the task. When I read the question, the following instantly came to mind:
p[i] <-> p[n-1]
i++, n--
loop until n <= i
Please note that you will want to check that 'n' is actually greater than 'i' before you make the first move. i.e.: it isn't a zero length string.
If this is a string of 1-byte characters, you want movzx edx, byte [eax] byte loads and mov [eax], dl byte stores.
You're doing 4-byte stores, which potentially steps on bytes past the end of the array. You also probably overread until you find a whole dword on the stack that's all zero. test edx, edx is fine if you correctly zero-extended a byte into EDX, but loading a whole word probably resulted in overread.
Use a debugger to see what you're doing to memory around the input arg.
(i.e. make sure you aren't writing past the end of the array, which is probably what happened here, stepping on the buffer-overflow detection cookie.)
The tutorial I am following is for x86 and was written using 32-bit assembly, I'm trying to follow along while learning x64 assembly in the process. This has been going very well up until this lesson where I have the following simple program which simply tries to modify a single character in a string; it compiles fine but segfaults when ran.
section .text
global _start ; Declare global entry oint for ld
_start:
jmp short message ; Jump to where or message is at so we can do a call to push the address onto the stack
code:
xor rax, rax ; Clean up the registers
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
; Try to change the N to a space
pop rsi ; Get address from stack
mov al, 0x20 ; Load 0x20 into RAX
mov [rsi], al; Why segfault?
xor rax, rax; Clear again
; write(rdi, rsi, rdx) = write(file_descriptor, buffer, length)
mov al, 0x01 ; write the command for 64bit Syscall Write (0x01) into the lower 8 bits of RAX
mov rdi, rax ; First Paramter, RDI = 0x01 which is STDOUT, we move rax to ensure the upper 56 bits of RDI are zero
;pop rsi ; Second Parameter, RSI = Popped address of message from stack
mov dl, 25 ; Third Parameter, RDX = Length of message
syscall ; Call Write
; exit(rdi) = exit(return value)
xor rax, rax ; write returns # of bytes written in rax, need to clean it up again
add rax, 0x3C ; 64bit syscall exit is 0x3C
xor rdi, rdi ; Return value is in rdi (First parameter), zero it to return 0
syscall ; Call Exit
message:
call code ; Pushes the address of the string onto the stack
db 'AAAABBBNAAAAAAAABBBBBBBB',0x0A
This culprit is this line:
mov [rsi], al; Why segfault?
If I comment it out, then the program runs fine, outputting the message 'AAAABBBNAAAAAAAABBBBBBBB', why can't I modify the string?
The authors code is the following:
global _start
_start:
jmp short ender
starter:
pop ebx ;get the address of the string
xor eax, eax
mov al, 0x20
mov [ebx+7], al ;put a NULL where the N is in the string
mov al, 4 ;syscall write
mov bl, 1 ;stdout is 1
pop ecx ;get the address of the string from the stack
mov dl, 25 ;length of the string
int 0x80
xor eax, eax
mov al, 1 ;exit the shellcode
xor ebx,ebx
int 0x80
ender:
call starter
db 'AAAABBBNAAAAAAAABBBBBBBB'0x0A
And I've compiled that using:
nasm -f elf <infile> -o <outfile>
ld -m elf_i386 <infile> -o <outfile>
But even that causes a segfault, images on the page show it working properly and changing the N into a space, however I seem to be stuck in segfault land :( Google isn't really being helpful in this case, and so I turn to you stackoverflow, any pointers (no pun intended!) would be appreciated
I would assume it's because you're trying to access data that is in the .text section. Usually you're not allowed to write to code segment for security. Modifiable data should be in the .data section. (Or .bss if zero-initialized.)
For actual shellcode, where you don't want to use a separate section, see Segfault when writing to string allocated by db [assembly] for alternate workarounds.
Also I would never suggest using the side effects of call pushing the address after it to the stack to get a pointer to data following it, except for shellcode.
This is a common trick in shellcode (which must be position-independent); 32-bit mode needs a call to get EIP somehow. The call must have a backwards displacement to avoid 00 bytes in the machine code, so putting the call somewhere that creates a "return" address you specifically want saves an add or lea.
Even in 64-bit code where RIP-relative addressing is possible, jmp / call / pop is about as compact as jumping over the string for a RIP-relative LEA with a negative displacement.
Outside of the shellcode / constrained-machine-code use case, it's a terrible idea and you should just lea reg, [rel buf] like a normal person with the data in .data and the code in .text. (Or read-only data in .rodata.) This way you're not trying execute code next to data, or put data next to code.
(Code-injection vulnerabilities that allow shellcode already imply the existence of a page with write and exec permission, but normal processes from modern toolchains don't have any W+X pages unless you do something to make that happen. W^X is a good security feature for this reason, so normal toolchain security features / defaults must be defeated to test shellcode.)
I have to define a function in assembly that will allow me to loop through a string of declared bytes and print them using a BIOS interrupt. I'm in 16 bit real mode. This is an exercise on writing a little bootloader from a textbook, but it seems that it was only a draft and it's missing some stuff.
I have been given the following code:
org 0x7c00
mov bx, HELLO_MSG
call print_string
mov bx, GOODBYE_MSG
call print_string
jmp $ ;hang so we can see the message
%include "print_string.asm"
HELLO_MSG:
db 'Hello, World!', 0
GOODBYE_MSG:
db 'Goodbye!', 0
times 510 - ($ - $$) db 0
dw 0xaa55
My print_string.asm looks like this:
print_string:
pusha
mov ah, 0x0e
loop:
mov al, bl
cmp al, 0
je return
int 0x10
inc bx
jmp loop
return:
popa
ret
I have some idea of what I'm doing, but the book doesn't explain how to iterate through something. I know how to do it in C but this is my first time using assembly for something other than debugging C code. What happens when I boot through the emulator is that it prints out a couple of lines of gibberish and eventually hangs there for me to see my failure in all it's glory. Hahaha.
Well, it looks like it loads the address of the string into the BX register before calling the function.
The actual function looks like it is trying to loop through the string, using BX as a pointer and incrementing it (inc bx) until it hits the ASCII NUL at the end of the string (cmp al, 0; je return)...
...but something is wrong. The "mov al, bl" instruction does not look correct, because that would move the low 8 bits of the address into al to be compared for an ASCII NUL, which does not make a lot of sense. I think it should be something more like "mov al, [bx]"; i.e. move the byte referenced by the BX address into the AL register -- although it has been a long time since I've worked with assembly so I might not have the syntax correct.
Because of that bug, the 10h interrupt would also be printing random characters based on the address of the string rather than the contents of the string. That would explain the gibberish you're seeing.
I think the issue is you cannot count on the int preserving any of your registers, so you need to protect them. Plus, what Steven pointed out regarding loading of your string address:
; Print the string whose address is in `bx`, segment `ds`
; String is zero terminated
;
print_string:
pusha
loop:
mov al, [bx] ; load what `bx` points to
cmp al, 0
je return
push bx ; save bx
mov ah, 0x0e ; load this every time through the loop
; you don't know if `int` preserves it
int 0x10
pop bx ; restore bx
inc bx
jmp loop
return:
popa
ret
Like strlen() from glibc that performs a nice bit manipulation and 4 bytes checked per time making the function so fast, compared to a byte-by-byte routine as most all others do, is there something like this to compare two strings in assembly? I'm reading some pages on code implementation for C language, very interested in strings-handling part, but I still not found none like this.
I have to make this function as fast possible because it's the heart of my application.(don't recommend hash table)
Any assembler is welcome. But I'm a bit familiar with intel's assembly syntax, if assembly that you'll go to provide is different, please comment it.
You can compare word by word (eg. 32-bits or 64-bits at a time). You just need to be careful not to go past the end of the string. If you are making the strings, then you could pad them with zeroes so they are a multiple of the word size, then you don't even need to check.
Assuming zero terminated strings (although the same applies for memcmp()); the fastest way to do string comparisons in assembly depends on the length/s of the strings, and the specific CPU.
In general; SSE or AVX has a high setup cost but gives faster throughput once it's running, which makes it the best choice if you're comparing very long strings (especially if most of the characters match).
Alternatively, something that does one byte at a time using general purpose registers will typically have a very low setup cost and lower throughput, which makes it the best choice if you're comparing lots of small strings (or even lots of large strings where the first few characters are likely to be different).
If you're doing this for a specific application, then you can determine the average number of characters compared and find the best approach for that average. You can also have different functions for different cases - e.g. implement a strcmp_small() and a strcmp_large() if there's a mixture.
Despite all this, if the performance of string comparisons matters a lot, then it's very likely that the fastest way to compare strings is not comparing strings at all. Basically, the words "I have to make this function as fast possible because it's the heart of my application" should make everyone wonder why better ways of implementing the application aren't possible.
StrCompCase (case sensitive) as implemented in FreshLib/strlib.asm library.
Here is some code that uses dword comparison:
Note, that is first checks the length of the strings. That is because in the mentioned library the strings are length-prefixed, so StrLen is instant O(1) and scanning for termination NULL is provided only as a fall back (see the Second part of this answer).
Comparing lengths before actual comparison allows to make the speed O(1) for different strings, which in case of searching big arrays may significantly improve the performance.
Then the comparison goes on dwords, and, at the end, if the string length is not multiply of 4, the remaining 1..3 bytes are compared byte by byte.
proc StrCompCase, .str1, .str2
begin
push eax ecx esi edi
mov eax, [.str1]
mov ecx, [.str2]
cmp eax, ecx
je .equal
test eax, eax
jz .noteq
test ecx, ecx
jz .noteq
stdcall StrLen, eax
push eax
stdcall StrLen, ecx
pop ecx
cmp eax, ecx
jne .noteq
stdcall StrPtr, [.str1]
mov esi,eax
stdcall StrPtr, [.str2]
mov edi,eax
mov eax, ecx
shr ecx, 2
repe cmpsd
jne .noteq
mov ecx, eax
and ecx, 3
repe cmpsb
jne .noteq
.equal:
stc
pop edi esi ecx eax
return
.noteq:
clc
pop edi esi ecx eax
return
endp
About StrLen code:
Here is the implementation of StrLen.
You can see, that if possible, it uses length prefixed strings, this way making the execution time O(1). If this is not possible it falls back into scanning algorithm that checks 8 bytes per cycle and it pretty fast, but still O(n).
proc StrLen, .hString ; proc StrLen [hString]
begin
mov eax, [.hString]
cmp eax, $c0000000
jb .pointer
stdcall StrPtr, eax
jc .error
mov eax, [eax+string.len]
clc
return
.error:
xor eax, eax
stc
return
.pointer:
push ecx edx esi edi
; align on dword
.byte1:
test eax, 3
jz .scan
cmp byte [eax], 0
je .found
inc eax
jmp .byte1
.scan:
mov ecx, [eax]
mov edx, [eax+4]
lea eax, [eax+8]
lea esi, [ecx-$01010101]
lea edi, [edx-$01010101]
not ecx
not edx
and esi, ecx
and edi, edx
and esi, $80808080
and edi, $80808080
or esi, edi
jz .scan
sub eax, 9
; byte 0 was found: so search by bytes.
.byteloop:
lea eax, [eax+1]
cmp byte [eax], 0
jne .byteloop
.found:
sub eax, [.hString]
clc
pop edi esi edx ecx
return
endp
Note that the zero terminated strings have both performance and security issues.
It is better to use size prefixed strings. For example, the mentioned library uses dynamic strings, where the string contains dword field at offset -4 (string.len in the above code) that contains the current length of the string.
First rule for faster then byte-per-byte comparison is to malloc the strings or .align 16 any constant strings to ensure
robustness against security violations (reading past allocated area)
best alignment for xxm (or 64-bit) processing
I'm trying to make a program using NASM that takes input from command line arguments. Since string length is not provided, I'm trying to make a function to compute my own. Here is my attempt, which takes a pointer to a string in the ebx register, and returns the length of the string in ecx:
len:
push ebx
mov ecx,0
dec ebx
count:
inc ecx
inc ebx
cmp ebx,0
jnz count
dec ecx
pop ebx
ret
My method is to go through the string, character by character, and check if it's null. If it's not, I increment ecx and go to the next character. I believe the problem is that cmp ebx,0 is incorrect for what I'm trying to do. How would I properly go about checking whether the character is null? Also, are there other things that I could be doing better?
You are comparing the value in ebx with 0 which is not what you want. The value in ebx is the address of a character in memory so it should be dereferenced like this:
cmp byte[ebx], 0
Also, the last push ebx should be pop ebx.
Here is how I do it in a 64-bit Linux executable that checks argv[1]. The kernel starts a new process with argc and argv[] on the stack, as documented in the x86-64 System V ABI.
_start:
pop rsi ; number of arguments (argc)
pop rsi ; argv[0] the command itself (or program name)
pop rsi ; rsi = argv[1], a pointer to a string
mov ecx, 0 ; counter
.repeat:
lodsb ; byte in AL
test al,al ; check if zero
jz .done ; if zero then we're done
inc ecx ; increment counter
jmp .repeat ; repeat until zero
.done:
; string is unchanged, ecx contains the length of the string
; unused, we look at command line args instead
section .rodata
asciiz: db "This is a string with 36 characters.", 0
This is slow and inefficient, but easy to understand.
For efficiency, you'd want
only 1 branch in the loop (Why are loops always compiled into "do...while" style (tail jump)?)
avoid a false dependency by loading with movzx instead of merging into the previous RAX value (Why doesn't GCC use partial registers?).
subtract pointers after the loop instead of incrementing a counter inside.
And of course SSE2 is always available in x86-64, so we should use that to check in chunks of 16 bytes (after reaching an alignment boundary). See optimized hand-written strlen implementations like in glibc. (https://code.woboq.org/userspace/glibc/sysdeps/x86_64/strlen.S.html).
Here how I would have coded it
len:
push ebx
mov eax, ebx
lp:
cmp byte [eax], 0
jz lpend
inc eax
jmp lp
lpend:
sub eax, ebx
pop ebx
ret
(The result is in eax). Likely there are better ways.