Hi guys, I haven't been here for a long time, now I'm back with a doubt hehe.  I'm using GAS, at&t syntax and I am trying to push a character into the stack,
push %al

but an error is returned to me
suffix or operands invalid for 'push'


Why can't I to push a byte into the stack?

Thanx in advance




Posted on 2012-04-11 13:21:43 by massem
Because your stack is not 8-bit.
It's either 16-bit (real mode/DOS/Win16), 32-bit (Win32, linux etc) or 64-bit (x64 version of Windows, linux etc).
You should always push the full register.
So if you are using 16-bit, push ax, if you use 32-bit, push eax, and if you use 64-bit, push rax.
Do the same when you pop, et voila, your byte is preserved (as is the rest of the register, which you may or may not care about).

You don't want to misalign your stack anyway.
Posted on 2012-04-11 14:10:08 by Scali
:( these are not good news. I want to concatenate characters and I don't know how. I thought that maybe push them into a stack.  Do u have any idea about how can I concatenate characters?

Thank u for your reply
Posted on 2012-04-11 14:46:03 by massem
If characters can generally be conceived of as byte-sized numerical values, then how would you go about concatenating them?
Posted on 2012-04-11 18:57:40 by SpooK

If characters can generally be conceived of as byte-sized numerical values, then how would you go about concatenating them?


Ups... I didn't know that...  mmm i don't know how to solve this problem. I have a string saved in a buffer, in this buffer I have an IP number. I would like to parse it in certain way that I can obtain the IP number. At the beginning, I thought to read the buffer every 4bytes, but then I realised what happens if the ip is like this 192.168.1.100 If I read it I will be received 192.168.1.100 plus garbage. Then I thought read character by character and concatenating.. but as Spook told me I can't do that.
So I don't have any clue how to solve it... any  idea?
Posted on 2012-04-12 06:39:46 by massem
Hi Marce,

To address the original question, while you can't push a single byte, you could subtract "enough" from %esp to make a buffer, and "movb" single bytes into this buffer to concatenate 'em. I'm not sure that's really what you want to do, though.

As I understand it, you've got an IP in the form of text - "192.192.1.100" - and you want to convert it to an integer(?). For internet/socket purposes, this probably wants to be in "standard byte order" - that is, big-endian (not really "standard" on x86).

As you probably know, I'm "devout Nasmist" but as it happens I have an "atoi" routine translated to Gas/AT&T syntax (helping "Anders"):

atoi:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp), %edx

xorl %eax, %eax # zero result
xorl %ebx, %ebx # and sign indicator
cmpb $'-', (%edx)
jnz getintloop
incl %edx # skip the '-'
incl %ebx # and set the "sign indicator"
getintloop:
movsx (%edx), %ecx # get a character
incl %edx # and get ready for next one
# make sure we have a valid character
cmpb $'0', %cl
jl invalid
cmpb $'9', %cl
ja invalid
# multiply result by ten, subtract '0' from character, and add it
leal (%eax, %eax, 4), %eax
leal -0x30(%ecx, %eax, 2), %eax

jmp getintloop
invalid:
testl %ebx, %ebx
jz ispositive
negl %eax
ispositive:
popl %ebx
movl %ebp, %esp
popl %ebp
ret

This is "C callable" - expects the address of the string on the stack, and returns an integer in %eax. It "trashes" %ecx and %edx (as C allows). It returns when it encounters any invalid character (not representing a decimal digit). It does not check for overflow, just "rolls over". While the C folk can only use the integer returned in %eax, in asm we can use the "trashed" %ecx and %edx as well! %ecx (just %cl, really) is the invalid character that ended processing - if it's '.', there's more to do. %edx is the "next position" in the string. To process "192.168.1.100", you'd call it four times, each time saving the value returned - it'll fit in a byte, even though it's in %eax - and shifting or rotating (depending if you want little-endian or big-endian) into a single 32-bit integer.

Is that what you want to do? Can you figure out how to use that "atoi" to do it? I think I have such a routine, but not in AT&T syntax. I can probably help you "translate" it but, to be honest, the more I use Gas, the better I like Nasm! See what you can do with it, if that's really what you want to do...

Best,
Frank

Posted on 2012-04-12 15:08:16 by fbkotler
Frank,


As I understand it, you've got an IP in the form of text - "192.192.1.100" - and you want to convert it to an integer(?). For internet/socket purposes, this probably wants to be in "standard byte order" - that is, big-endian (not really "standard" on x86).


Hrm, I totally didn't read his post that way. The way I read his question, he has a string
which (amongst other things) contains an IP address and he wants to tokenize the IP out of
the string.

massem,

If that's the case, then it would be really nice if you could share with us an example of the
string itself. Given that the IP number is the first digit based token in the string, my approach would be to scan the string for
byte(0x20)'s and checking the next byte for a numeric value. Upon finding a numeric value, I
would save the index to that byte and then scan until I saw 3 byte(0x2E)'s followed by another
byte(0x20). When I reached this byte(0x20) I would replace it with a byte(0) and treat the
stored index as a pointer to the string. If I haven't completely confused you, try giving us
an example of the text and I might be able to draft up an example. (As it is, I'm running DOS
and posting on the forum is a bit of a pain. :P)

Regards,
Bryant

Posted on 2012-04-15 02:24:03 by Synfire
Yeah, I think I did a:

jmp hasty_conclusion


Suppose, for the sake of argument, that we have a buffer with some text in it. We suspect that this text may (or may not) include an IP in the form of a "dotted quad" (or more than one?) - not necessarily the first or only numerical value. Would a routine to extract any such pattern(s) make an "interesting exercise"?

Best,
Frank

Posted on 2012-04-15 23:35:10 by fbkotler
Hi guys, thanks for your replies.  My program intends to connect to whatismyip.com, receive the response from the server and then parsing it in order to obtain the ip assigned.  Finally, this ip is saved in a file.
I could do almost everything... my big problem is related to the parsing. 
For instance I have this response:
HTTP/1.1 200 OK
Content-Type: text/javascript; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
....
....
200.69.104.1


I saved the response in a buffer and I parsed it up to the ip, discarding the characters which are not the ip. Now, it's time to read the ip and save it in another buffer. My idea was to use "lodsb" to load a single byte in %al and then push it into a stack.. but.. you told me I cannot do that.... so... how can I obtain the ip in the right order to, later, be saved in a file?

thanx in advance
marce

Posted on 2012-04-20 14:54:03 by massem
Heh. I wondered if this was still "getmyip" (I think you called it "iplog"?). What I found was that the first read of the socket (after sending our request) was "cruft" and the second read was our IP. I wasn't sure it "always" happened that way, so I didn't count on that. I did ASSume that our IP was the last thing in the buffer and "backed up" to find the beginning. Knowing where it started and the length, I just wrote it to stdout... but any other file descriptor should work. Don't really need to move it to a separate buffer unless you want to.

But if you've got a character in %al - via lodsb or some other way - you could move it to another buffer with stosb (or some other way). If you want to push/pop, you could pushl %eax - just remember when you popl it, only one byte is "interesting"...

It occurred to me that asking a remote host what our IP is must be the "hard way". My machine must know what my IP is! AFAIK, it's part of an outgoing packet but is apparently "hidden" in the bowels of the socketcall mechanism. There "must" be a way to access this information, but I don't know what it is. Any ideas?

Best,
Frank

Posted on 2012-04-21 00:53:51 by fbkotler
After creating a socket the function bind will attach a newly created socket to an address and port on your local machine.  Simply use getsockname to retrieve which address and port is associated with that socket.
Posted on 2012-04-21 10:14:25 by p1ranha

It occurred to me that asking a remote host what our IP is must be the "hard way". My machine must know what my IP is! AFAIK, it's part of an outgoing packet but is apparently "hidden" in the bowels of the socketcall mechanism. There "must" be a way to access this information, but I don't know what it is. Any ideas?


Your machine knows what your IPs (plural) are (you can have multiple network interfaces, and even multiple IPs per network interface).
I believe the usual way to obtain your IPs is this:
1) Use gethostname() to get the hostname of your machine
2) Use getaddrinfo() to get the list of IPs for your hostname.
(or the older, deprecated function gethostbyname(), which also returns a list of IPs).
Posted on 2012-04-21 15:22:28 by Scali
I'm absolutely horrible in GAS code, the AT&T syntax totally throws me for  a loop. lol

That being said (and using Frank's atoi code as a reference) I came up with this code to give you an idea of what to do. This function takes the address of the buffer containing your HTTP response from the whatismyip.com automation page and the size of the buffer as it's parameters.

get_ip:
pushl %ebp
movl %esp, %ebp

movl 8(%ebp), %esi
movl 12(%ebp), %ecx

find_previous_newline:
movb (%esi, %ecx, 1), %al
decl %ecx

cmpb $'\n', %al
jne find_previous_newline

incl %ecx
incl %ecx

leal (%esi, %ecx, 1), %eax

movl %ebp, %esp
popl %ebp
ret


I hope this works for ya.

EDIT The following is a test I ran while I was under linux. Worked fine.

.text

.globl _start
_start:
pushl $response_size
pushl $response
call get_ip

movl $response_size, %edx
subl %ecx, %edx
movl %eax, %ecx
movl $1, %ebx
movl $4, %eax
int $0x80

movl $0, %ebx
movl $1, %eax
int $0x80

# get_ip(s, l)
# @brief extract the IP from the end of input.
# @param s : address of the source string.
# @param l : length of the source string.
# @return eax : pointer to beginning of IP.
# @return ecx : number of bytes from end of string.
get_ip:
pushl %ebp
movl %esp, %ebp

movl 8(%ebp), %esi
movl 12(%ebp), %ecx

find_previous_newline:
movb (%esi, %ecx, 1), %al
decl %ecx

cmpb $'\n', %al
jne find_previous_newline

incl %ecx
incl %ecx

leal (%esi, %ecx, 1), %eax

movl %ebp, %esp
popl %ebp
ret

.data

response:
.ascii "HTTP/1.1 200 OK\r\nContent-Type: text/javascript; charset=UTF-8\r\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\r\n\r\n200.69.104.1"
response_size = . - response
Posted on 2012-04-23 23:20:25 by Synfire