Hi
I'm reading this article (http://database.sarang.net/study/linux/asm/linux-asm.txt) to learn some basic ASM stuff.
When I try to compile the example, I get this error:
args.s: Assembler messages:
args.s:30: Error: bad or irreducible absolute expression
args.s:30: Error: expecting scale factor of 1, 2, 4, or 8: got `$1'
My args.s source file looks like this:
.section .data
new_line_char:
.byte 0x0a
.section .text
.globl main
.align 4
main:
movl %esp, %ebp #store esp in ebp
again: addl $4, %esp #next param on stack (+4)
movl (%esp),%eax #move next praameter into %eax
testl %eax,%eax # %eax == NULL?
jz end_again #jump to end_again if eax==null
call putstring
jmp again
end_again:
xorl %eax,%eax #eax = 0
incl %eax #eax = 1, system call exit
xorl %ebx,%ebx #parameter 0 for exit
int $0x80
putstring: .type @function
pushl %ebp
movl %esp, %ebp
movl 8(%ebp),%ecx
xorl %edx,%edx
count_chars:
movb (%ecx,%edx,$1), %al
testb %al,%al
jz done_count_chars
incl %edx
jmp count_chars
done_count_chars:
movl $4, %eax
xorl %ebx,%ebx
incl %ebx
int $0x80
movl $4, %eax
leal new_line_char, %ecx
xorl %edx,%edx
incl %edx
int $0x80
movl %ebp,%esp
popl %ebp
ret
The problem is on this line:
movb (%ecx,%edx,$1), %al
Could anyone please explain me what that line should do?
And I have also a little question on this line:
movl 8(%ebp),%ecx
what does it do? What does the 8 before the brackets mean? I think 8+ value in the ebp register. Is that correct?
Thanks in advance!
It's been a while since I worked/played with RPG but, yes, the last question about the 8, it is a scale factor.
Paul
Sorry but THAT code is apparently using the AT&T syntax. That syntax was designed as a compiler backend and not for humans usage although there are humans that like it.
The parameters order are reversed, all registers have a "%" suffix, all numbers have a "$" suffix and a lot of other stupid notations (IMHO) that are designed to help the parser / compiler but will annoy me beyond the level where I could help.
This is mainly a MASM forum and because of this you will get much faster and better answers if you use Intel syntax. Hence if possible I would recommend that you convert it to MASM or Intel syntax and then you might get better help here. I have heard that GAS does have a switch for allowing Intel syntax.
With great "pain" and a lot of guessing:
movb (%ecx,%edx,$1), %al
This should translate to:
mov al,[ecx+1*edx]
I guess this will move a byte value from the memory location who's address is computed as: ecx+scale*edx to the AL register (8 bits register).
As described in the Intel CPU manuals, this kind of ModRM expressions used in indirect addressing have a template of:
[base_register + scale*index_register + offset]
Only God and GAS manuals know what the (%ecx,%edx,$1) notation does mean in this context.
I will take a wild guess and consider this:
base_register = ecx
index_register = edx
scale = $1
offset = 0 / missing
Under this circumstances one should observe that the CPU only accepts 1, 2, 4,and 8 for scale values (powers of 2) and I also guess that the $1 is considered by default when an an index_register is present and hence using $1 as a "scale" is reported as an error... arguably a bug or maybe an undocumented feature...
While this line:
movl 8(%ebp),%ecx
Should translate to:
mov ecx,[ebp+8]
This will move into ecx the dword at address calculated as EBP+8. I guess this is a local argument for the function since it uses an EBP based stack frame.
Sorry if this is based on a lot of guess work...
The AT&T syntax
movb (%ecx,%edx,$1), %al
from what I can put together it would be Intel syntax
mov al, [ecx+edx*1]
It loads a copy of the byte value at memory address formed by ecx plus edx*scale
and stores it in the al register.
Choxo,
There is a GAS reference here (http://sources.redhat.com/binutils/docs-2.12/as.info/index.html), and information on the 386 dependent features here (http://sources.redhat.com/binutils/docs-2.12/as.info/i386-Dependent.html#i386-Dependent).
Per here (http://sources.redhat.com/binutils/docs-2.12/as.info/i386-Syntax.html#i386-Syntax), in the AT&T syntax immediate operands are preceded by a '$' and register operands by a '%'.
Per here (http://sources.redhat.com/binutils/docs-2.12/as.info/i386-Memory.html#i386-Memory), displacements are handled like this:
AT&T: -4(%ebp), Intel: [ebp - 4]
And scaling factors like this:
AT&T: foo(,%eax,4), Intel: [foo + eax*4]
Also, when I try to assemble the source with a fairly recent version of GAS, for line 24 I get:
att.asm:24: Warning: .type pseudo-op used outside of .def/.endef ignored.
att.asm:24: Error: junk at end of line, first unrecognized character is `@'
Thank you all for the information.
I'll read it and start using Intel syntax instead...