Hey all, was doing some asm inside a C++ project. Setup: VS2010, custom build for .asm file using ml64.

ml64 args:
ml64 -c -Zi "-Fl$(IntDir)%(FileName).lst" "-Fo$(IntDir)%(FileName).obj" "%(FullPath)"

The function where I'm having an issue is a member function, operator*. ml64 doesn't emit the ret instruction at the end of the code, so it screws up everything ofc.

Here's the entire asm file:


.code




; const UBigInt& UBigInt::operator+(UBigInt const &) const

;??GUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??GUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP




; const UBigInt& UBigInt::operator-(UBigInt const &) const

;??HUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??HUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP




; const UBigInt UBigInt::operator*(const UBigInt& a_int) const

??DUBigInt@@QEBA?BV0@AEBV0@@Z PROC FRAME thisptr:PTR QWORD, bigint:PTR QWORD

??0UBigInt@@QEAA@AEBV?$vector@_JV?$allocator@_J@std@@@std@@@Z PROTO
UBigInt_UBigInt EQU ??0UBigInt@@QEAA@AEBV?$vector@_JV?$allocator@_J@std@@@std@@@Z

??0?$vector@_JV?$allocator@_J@std@@@std@@QEAA@_K@Z PROTO
??A?$vector@_JV?$allocator@_J@std@@@std@@QEAAAEA_J_K@Z PROTO
?size@?$vector@_JV?$allocator@_J@std@@@std@@QEBA_KXZ PROTO
?push_back@?$vector@_JV?$allocator@_J@std@@@std@@QEAAX$$QEA_J@Z PROTO
??1?$vector@_JV?$allocator@_J@std@@@std@@QEAA@XZ PROTO

vector_vector EQU ??0?$vector@_JV?$allocator@_J@std@@@std@@QEAA@_K@Z
vector_index EQU ??A?$vector@_JV?$allocator@_J@std@@@std@@QEAAAEA_J_K@Z
vector_size EQU ?size@?$vector@_JV?$allocator@_J@std@@@std@@QEBA_KXZ
vector_push_back EQU ?push_back@?$vector@_JV?$allocator@_J@std@@@std@@QEAAX$$QEA_J@Z
vector_decvector EQU ??1?$vector@_JV?$allocator@_J@std@@@std@@QEAA@XZ

; stack layout
;
; 0xA8 --------------------- < end of 32 bytes shadow space
; rbx
; 0xA0 ---------------------
; rdi
; 0x98 ---------------------
; rsi
; 0x90 ---------------------
; r12
; 0x88 --------------------- < start of 32 bytes shadow space
; return address
; 0x80 ---------------------
; rbp, automatically pushed with autogenerated code
; 0x78 --------------------- < old rsp
; r13
; 0x70 ---------------------
; r14
; 0x68 ---------------------
; r15
; 0x60 ---------------------
; rcx
; 0x58 ---------------------
; r8
; 0x50 ---------------------
; rdx
; 0x48 ---------------------
; vector for outputted UBigInt
;
; 40 bytes
; 0x20 ---------------------
; 32 bytes shadow space for called functions
; 0x00 --------------------- < rsp

mov qword ptr , rbx
.pushreg rbx
mov qword ptr , rdi
.pushreg rdi
mov qword ptr , rsi
.pushreg rsi
mov qword ptr ,  r12
.pushreg r12
sub rsp, 78h
mov qword ptr , r13
.pushreg r13
mov qword ptr , r14
.pushreg r14
mov qword ptr , r15
.pushreg r15

.endprolog

mov qword ptr , rcx
mov qword ptr , r8
mov qword ptr , rdx

mov r14, r8

; this ptr already in rcx
call vector_size
mov esi, eax

mov rcx, r14
call vector_size
mov edi, eax

; construct vector for outputted UBigInt
; with size: b.size() + a.size() - 1
; also fill vector with all 0s

mov edx, edi
add edx, esi
sub edx, 1

lea rcx,
call vector_vector

;
; rbx: last overflow
; r14: a, a*b
; r15: overflow
; edi: b.size()
; esi: a.size()
; r12d: x
; r13d: y
;
; for (int x = 0; x < b.size (); ++x)
; {
; for (int y = 0; y < a.size (); ++y)
; {
; c += a*b + overflow;
;  }
; }

mov rbx, 0
mov r12d, 0

XLoopStart:
cmp r12d, edi
jge XLoopEnd

mov r13d, 0

YLoopStart:
cmp r13d, esi
jge YLoopEnd

mov edx, r13d
mov rcx, qword ptr
call vector_index
mov r14, qword ptr

mov edx, r12d
mov rcx, qword ptr
call vector_index
mov rax, qword ptr

mul r14
mov r14, rax
mov r15, rdx

mov edx, r12d
add edx, r13d
lea rcx,
call vector_index

add qword ptr , r14
add qword ptr , rbx

adc r15, 0
mov rbx, r15

inc r13d
jmp YLoopStart
YLoopEnd:

inc r12d
jmp XLoopStart
XLoopEnd:

jnc NoOverflow

mov edx, r12d
add edx, r13d
lea rcx,
call vector_push_back

NoOverflow:

; construct returned UBigInt

lea rdx,
mov rcx, qword ptr
call UBigInt_UBigInt


; deconstruct vector for returned UBigInt

lea rcx,
call vector_decvector

mov rax, qword ptr

mov rbx, qword ptr
mov rdi, qword ptr
mov rsi, qword ptr
mov r12, qword ptr
mov r13, qword ptr
mov r14, qword ptr
mov r15, qword ptr

add rsp, 78h

ret

??DUBigInt@@QEBA?BV0@AEBV0@@Z ENDP




; const UBigInt& UBigInt::operator/(UBigInt const &) const

;??KUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??KUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP

end


Here's what the assembler's listing shows:


Microsoft (R) Macro Assembler (x64) Version 10.00.30319.01  01/31/12 01:21:13
C:\Users\mikfig\documents\visual studio 2010\Projects\projectEuler\problem 20\biguint_mul.asm  Page 1 - 1


00000000 .code




; const UBigInt& UBigInt::operator+(UBigInt const &) const

;??GUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??GUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP




; const UBigInt& UBigInt::operator-(UBigInt const &) const

;??HUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??HUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP




; const UBigInt UBigInt::operator*(const UBigInt& a_int) const

00000000 ??DUBigInt@@QEBA?BV0@AEBV0@@Z PROC FRAME thisptr:PTR QWORD, bigint:PTR QWORD

??0UBigInt@@QEAA@AEBV?$vector@_JV?$allocator@_J@std@@@std@@@Z PROTO
= ??0UBigInt@@QEAA@AEBV?$v UBigInt_UBigInt EQU ??0UBigInt@@QEAA@AEBV?$vector@_JV?$allocator@_J@std@@@std@@@Z
  ector@_JV?$allocator@_J@
  std@@@std@@@Z

??0?$vector@_JV?$allocator@_J@std@@@std@@QEAA@_K@Z PROTO
??A?$vector@_JV?$allocator@_J@std@@@std@@QEAAAEA_J_K@Z PROTO
?size@?$vector@_JV?$allocator@_J@std@@@std@@QEBA_KXZ PROTO
?push_back@?$vector@_JV?$allocator@_J@std@@@std@@QEAAX$$QEA_J@Z PROTO
??1?$vector@_JV?$allocator@_J@std@@@std@@QEAA@XZ PROTO

= ??0?$vector@_JV?$allocat vector_vector EQU ??0?$vector@_JV?$allocator@_J@std@@@std@@QEAA@_K@Z
  or@_J@std@@@std@@QEAA@_K
  @Z
= ??A?$vector@_JV?$allocat vector_index EQU ??A?$vector@_JV?$allocator@_J@std@@@std@@QEAAAEA_J_K@Z
  or@_J@std@@@std@@QEAAAEA
  _J_K@Z
= ?size@?$vector@_JV?$allo vector_size EQU ?size@?$vector@_JV?$allocator@_J@std@@@std@@QEBA_KXZ
  cator@_J@std@@@std@@QEBA
  _KXZ
= ?push_back@?$vector@_JV? vector_push_back EQU ?push_back@?$vector@_JV?$allocator@_J@std@@@std@@QEAAX$$QEA_J@Z
  $allocator@_J@std@@@std@
  @QEAAX$$QEA_J@Z
= ??1?$vector@_JV?$allocat vector_decvector EQU ??1?$vector@_JV?$allocator@_J@std@@@std@@QEAA@XZ
  or@_J@std@@@std@@QEAA@XZ

; stack layout
;
; 0xA8 --------------------- < end of 32 bytes shadow space
; rbx
; 0xA0 ---------------------
; rdi
; 0x98 ---------------------
; rsi
; 0x90 ---------------------
; r12
; 0x88 --------------------- < start of 32 bytes shadow space
; return address
; 0x80 ---------------------
; rbp, automatically pushed with autogenerated code
; 0x78 --------------------- < old rsp
; r13
; 0x70 ---------------------
; r14
; 0x68 ---------------------
; r15
; 0x60 ---------------------
; rcx
; 0x58 ---------------------
; r8
; 0x50 ---------------------
; rdx
; 0x48 ---------------------
; vector for outputted UBigInt
;
; 40 bytes
; 0x20 ---------------------
; 32 bytes shadow space for called functions
; 0x00 --------------------- < rsp

00000000  48/ 89 5C 24 mov qword ptr , rbx
  20
.pushreg rbx
00000005  48/ 89 7C 24 mov qword ptr , rdi
  18
.pushreg rdi
0000000A  48/ 89 74 24 mov qword ptr , rsi
  10
.pushreg rsi
0000000F  4C/ 89 64 24 mov qword ptr ,  r12
  08
.pushreg r12
00000014  48/ 83 EC 78 sub rsp, 78h
00000018  4C/ 89 6C 24 mov qword ptr , r13
  70
.pushreg r13
0000001D  4C/ 89 74 24 mov qword ptr , r14
  68
.pushreg r14
00000022  4C/ 89 7C 24 mov qword ptr , r15
  60
.pushreg r15

.endprolog

00000027  48/ 89 4C 24 mov qword ptr , rcx
  58
0000002C  4C/ 89 44 24 mov qword ptr , r8
  50
00000031  48/ 89 54 24 mov qword ptr , rdx
  48

00000036  4D/ 8B F0 mov r14, r8

; this ptr already in rcx
00000039  E8 00000000 E call vector_size
0000003E  8B F0 mov esi, eax

00000040  49/ 8B CE mov rcx, r14
00000043  E8 00000000 E call vector_size
00000048  8B F8 mov edi, eax

; construct vector for outputted UBigInt
; with size: b.size() + a.size() - 1
; also fill vector with all 0s

0000004A  8B D7 mov edx, edi
0000004C  03 D6 add edx, esi
0000004E  83 EA 01 sub edx, 1

00000051  48/ 8D 4C 24 lea rcx,
  20
00000056  E8 00000000 E call vector_vector

;
; rbx: last overflow
; r14: a, a*b
; r15: overflow
; edi: b.size()
; esi: a.size()
; r12d: x
; r13d: y
;
; for (int x = 0; x < b.size (); ++x)
; {
; for (int y = 0; y < a.size (); ++y)
; {
; c += a*b + overflow;
;  }
; }

0000005B  48/ C7 C3 mov rbx, 0
  00000000
00000062  41/ BC mov r12d, 0
  00000000

00000068 XLoopStart:
00000068  44/ 3B E7 cmp r12d, edi
0000006B  7D 5B jge XLoopEnd

0000006D  41/ BD mov r13d, 0
  00000000

00000073 YLoopStart:
00000073  44/ 3B EE cmp r13d, esi
00000076  7D 4B jge YLoopEnd

00000078  41/ 8B D5 mov edx, r13d
0000007B  48/ 8B 4C 24 mov rcx, qword ptr
  58
00000080  E8 00000000 E call vector_index
00000085  4C/ 8B 30 mov r14, qword ptr

00000088  41/ 8B D4 mov edx, r12d
0000008B  48/ 8B 4C 24 mov rcx, qword ptr
  50
00000090  E8 00000000 E call vector_index
00000095  48/ 8B 00 mov rax, qword ptr

00000098  49/ F7 E6 mul r14
0000009B  4C/ 8B F0 mov r14, rax
0000009E  4C/ 8B FA mov r15, rdx

000000A1  41/ 8B D4 mov edx, r12d
000000A4  41/ 03 D5 add edx, r13d
000000A7  48/ 8D 4C 24 lea rcx,
  20
000000AC  E8 00000000 E call vector_index

000000B1  4C/ 01 30 add qword ptr , r14
000000B4  48/ 01 18 add qword ptr , rbx

000000B7  49/ 83 D7 00 adc r15, 0
000000BB  49/ 8B DF mov rbx, r15

000000BE  41/ FF C5 inc r13d
000000C1  EB B0 jmp YLoopStart
000000C3 YLoopEnd:

000000C3  41/ FF C4 inc r12d
000000C6  EB A0 jmp XLoopStart
000000C8 XLoopEnd:

000000C8  73 10 jnc NoOverflow

000000CA  41/ 8B D4 mov edx, r12d
000000CD  41/ 03 D5 add edx, r13d
000000D0  48/ 8D 4C 24 lea rcx,
  20
000000D5  E8 00000000 E call vector_push_back

000000DA NoOverflow:

; construct returned UBigInt

000000DA  48/ 8D 54 24 lea rdx,
  20
000000DF  48/ 8B 4C 24 mov rcx, qword ptr
  48
000000E4  E8 00000000 E call UBigInt_UBigInt


; deconstruct vector for returned UBigInt

000000E9  48/ 8D 4C 24 lea rcx,
  20
000000EE  E8 00000000 E call vector_decvector

000000F3  48/ 8B 44 24 mov rax, qword ptr
  48

000000F8  48/ 8B 9C 24 mov rbx, qword ptr
  00000098
00000100  48/ 8B BC 24 mov rdi, qword ptr
  00000090
00000108  48/ 8B B4 24 mov rsi, qword ptr
  00000088
00000110  4C/ 8B A4 24 mov r12, qword ptr
  00000080
00000118  4C/ 8B 6C 24 mov r13, qword ptr
  70
0000011D  4C/ 8B 74 24 mov r14, qword ptr
  68
00000122  4C/ 8B 7C 24 mov r15, qword ptr
  60

00000127  48/ 83 C4 78 add rsp, 78h

ret

0000012B ??DUBigInt@@QEBA?BV0@AEBV0@@Z ENDP




; const UBigInt& UBigInt::operator/(UBigInt const &) const

;??KUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??KUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP

end
Microsoft (R) Macro Assembler (x64) Version 10.00.30319.01  01/31/12 01:21:13
C:\Users\mikfig\documents\visual studio 2010\Projects\projectEuler\problem 20\biguint_mul.asm  Symbols 2 - 1




Procedures, parameters, and locals:

                N a m e                Type    Value    Attr

??0?$vector@_JV?$allocator@_J@std@@@std@@QEAA@_K@Z . P       00000000 Length= 00000000 External
??0UBigInt@@QEAA@AEBV?$vector@_JV?$allocator@_J@std@@@std@@@Z  P        00000000 Length= 00000000 External
??1?$vector@_JV?$allocator@_J@std@@@std@@QEAA@XZ . P     00000000 Length= 00000000 External
??A?$vector@_JV?$allocator@_J@std@@@std@@QEAAAEA_J_K@Z . P   00000000 Length= 00000000 External
??DUBigInt@@QEBA?BV0@AEBV0@@Z  . P 00000000 _TEXT Length= 0000012B Public
  thisptr  . . . . . . . . . . . QWord rbp + 00000010
  bigint . . . . . . . . . . . . QWord rbp + 00000018
  XLoopStart . . . . . . . . . . L 00000068 _TEXT
  YLoopStart . . . . . . . . . . L 00000073 _TEXT
  YLoopEnd . . . . . . . . . . . L 000000C3 _TEXT
  XLoopEnd . . . . . . . . . . . L 000000C8 _TEXT
  NoOverflow . . . . . . . . . . L 000000DA _TEXT
?push_back@?$vector@_JV?$allocator@_J@std@@@std@@QEAAX$$QEA_J@Z  P   00000000 Length= 00000000 External
?size@?$vector@_JV?$allocator@_J@std@@@std@@QEBA_KXZ . P        00000000 Length= 00000000 External


Symbols:

                N a m e                Type    Value    Attr

$xdatasym  . . . . . . . . . . . Byte 00000000 _XDATA
UBigInt_UBigInt  . . . . . . . . Text  ??0UBigInt@@QEAA@AEBV?$vector@_JV?$allocator@_J@std@@@std@@@Z
vector_decvector . . . . . . . . Text  ??1?$vector@_JV?$allocator@_J@std@@@std@@QEAA@XZ
vector_index . . . . . . . . . . Text  ??A?$vector@_JV?$allocator@_J@std@@@std@@QEAAAEA_J_K@Z
vector_push_back . . . . . . . . Text  ?push_back@?$vector@_JV?$allocator@_J@std@@@std@@QEAAX$$QEA_J@Z
vector_size  . . . . . . . . . . Text  ?size@?$vector@_JV?$allocator@_J@std@@@std@@QEBA_KXZ
vector_vector  . . . . . . . . . Text  ??0?$vector@_JV?$allocator@_J@std@@@std@@QEAA@_K@Z

  0 Warnings
  0 Errors


Oh and the function I'm referring to is the only real function here: ??DUBigInt@@QEBA?BV0@AEBV0@@Z
Heh, and don't ask why im doing C++ stuff in asm.

Anybody got any ideas as to why the assembler doesn't emit 'ret'?

Thanks :),
mikfig
Posted on 2012-01-31 04:12:50 by mikfig
I don't see a ret in the source, so why would ML64 emit an instruction that isn't there?
Posted on 2012-01-31 07:37:16 by Scali
It's at the very bottom:


.code
...
??DUBigInt@@QEBA?BV0@AEBV0@@Z PROC FRAME thisptr:PTR QWORD, bigint:PTR QWORD
...
mov rbx, qword ptr
mov rdi, qword ptr
mov rsi, qword ptr
mov r12, qword ptr
mov r13, qword ptr
mov r14, qword ptr
mov r15, qword ptr

add rsp, 78h

ret

??DUBigInt@@QEBA?BV0@AEBV0@@Z ENDP




; const UBigInt& UBigInt::operator/(UBigInt const &) const

;??KUBigInt@@QEBAAEBV0@AEBV0@@Z PROC thisptr:DQ, bigint:DQ

;mov rax, rcx

;??KUBigInt@@QEBAAEBV0@AEBV0@@Z ENDP

end
Posted on 2012-01-31 13:39:14 by mikfig