Good! Looks like you're trying a worthwhile optimization over what I showed you...
;Program to convert number to string
;Arc-PC
;7 June 2012
SECTION .data
msg db 'hey! I am there always', 10
len equ $-msg
msg2 db 10
len2 equ $-msg2
msg3 db 0
SECTION .bss
SECTION .data
You probably want "section .text" here. There are some "flags" (just a bit in a dword) set in the linkable object file header which is passed on to the executable file header. One of them indicates "writeable" (otherwise it's "read only") and another indicates "executable". A ".text" section is supposed to be "read only" (the "writable" bit is clear) and "executable" (bit set to one). It won't hurt to make the code section writable (although there may be some "security" implications). My CPU, and apparently yours, will actually execute code even if the "executable" bit is clear. However, I understand that some newer CPUs have an "NX" bit which will prevent execution in a section that doesn't have the "executable" bit set in the section header (I can't confirm this from my own experience, but that's what I'm told). So I think it's "safer" to let Nasm set these bits the way they're "supposed" to be. Nasm "knows" several section names (see the Manual) - note that "SECTION" can be either upper or lower case, but the name must be lowercase!
global _start
_start:
;for 32 bit divison, Processor assumes dividend to be of 64 bits, upper 32 in EDX, lower 32 in EAX
;Divisor is supposed to be provided explitly, like div ebx -> divide EDX EAX by EBX
;Quotient is stored in EAX and Remainder in EDX
mov eax, 1250 ;A number to be changed
mov ebx, 10 ;To be divided by 10
mov ecx, 0
loopend:
xor edx, edx
div ebx ;Divide it
add edx, '0'
push edx
inc ecx
cmp eax, ebx ;CHeck whether quotient gets zero
jle exit
Good! If eax is less than 10, the final digit is in eax and we can save a "div" (a very slow instruction) by stopping here. I don't think we want to stop if eax = 10! Also... "jl" is for signed integers, "jb" is for unsigned integers. Neither Nasm nor the CPU knows whether we intend an integer to be treated as signed or unsigned, we need to use different instructions. If the high bit of eax (bit 31) were set, "jl" would take the jump, since eax would be negative if treated as signed. "jb" would take the jump all the way up to eax = 0xFFFFFFFF - eax would be "below", but not "less" (if that makes any sense). This is why the C language is picky about "types"! If you try to compare an "int" with a "uint", the compiler will squawk. It needs to generate different code for a signed comparison or an unsigned comparison. You can fix this with a "cast", but this could potentially hide subtle errors - better to make the variables the same "type" in the first place (I did not understand this when I was trying to teach myself C - I thought the compiler was being "nit-picky" with me - but now I understand "why" - an advantage to learning asm!). In this case, I don't see how eax could ever have the high bit set (potentially "negative" if we treat it as signed), so it shouldn't make any difference... but "jb" would be "more correct". "jl" should work, but I don't think you want the "e" - if eax is 10 exactly we need one more "div". (I don't think we actually want to jump to "exit" at this point, but that'll work itself out)
loop loopend ;looping the loopend
I don't think you want to "loop" at this point. You increment ecx to count each digit, "loop" decrements ecx each time. So "loop" will continue forever since we increment ecx, but ecx won't count digits either, since "loop" decrements it! If I understand where you're going with this, you want an unconditional "jmp" here. It won't become an infinite loop since you've got an "exit condition" elsewhere.
exit:
mov eax, 1 ;Setting up the EXIT Ccall
mov ebx, 0 ;Setting up the return status to OS
int 80h ;Yo ! Kernel do it.
As I'm sure you know, we aren't quite ready to exit yet. When the "div" has gotten eax "below" (or "less than"... but not equal) 10, eax is our final digit. We still need to save (and count) this digit. We can "add '0'" either before or after pushing (or saving by another method) to "convert" number to character, as long as we do it someplace. You'll get to that...
It is entirely possible to use some other register besides ecx as a counter. "loop" uses ecx, but we can do the same thing with...
dec esi
; or sub esi, 1
; or lea esi, [esi -1]
jnz looptop
You actually use "loopend:" for this label - a terrible name for a label at the top of a loop! It doesn't matter to the "code" - the name is replaced by a number (the address of the label) - but for the sake of the poor "coder", "meaningful" names for labels or variables help a lot. (that's a nit-pick!)
As you observe, "push" is not a convenient way to save a value, since we're using the stack for our digits. What I did in the code I posted, was to save the "digit count" in another register. I used edx - since we're done with the "div" at this point, it's free for our use. Since I wanted to return the digit count, eax would have been convenient, but "stosb" uses al (a part of eax) and edi (es:edi actually, but in Windows/Linux/BSD segment registers all point to the same memory - this might not be the case in "your OS"... it isn't in dos!) "stosb" does:
mov [edi], al
inc edi
You can do the same thing, using other registers. I used "stosb" because it's short - one byte - but not particulary fast, and it depends on specific registers - there may not be much "advantage" to it.
As I mentioned, there are other ways of doing this. For example, we can get the digits in the "right order" by starting at the "end" of the buffer and working "backwards" as we get the digits, instead of pushing and popping them. This has the disadvantage that we don't know where the actual text representing the number starts. Since we're not using C, we can return more than one value. I've written a "number to text" routine that returns the "start of buffer" in ecx and the "length" in edx - all ready for the call to "print". Fairly "efficient" but potentially confusing, since it's not "standard" and definitely not "portable"!
Another approach is to avoid the slow "div" instruction entirely. It is possible to write a faster routine by using repeated "sub"s... or by using the reciprocal of 10 and using "mul" (this involves "fixed point" code). I don't have examples of either of these methods, but could probably(?) figure it out if I had to... Using "div" is slow, but "easy"...
You'll learn a lot by trying it yourself - learning what doesn't work is almost as valuable as learning what does work! So... "carry on!"
I can't help you with the phone problem.
Best,
Frank