The following source code causes a wrong assembly output :
1 "main.cpp" # 1 "<built-in>" # 1 "<command-line>" # 1 "main.cpp" # 1 "far_pointers.h" 1 # 13 "far_pointers.h" # 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.0/include/stddef.h" 1 3 4 # 149 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.0/include/stddef.h" 3 4 typedef int ptrdiff_t; # 211 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.0/include/stddef.h" 3 4 typedef unsigned int size_t; # 14 "far_pointers.h" 2 template <class T> class far_pointer { protected: unsigned short segmentSelector; T* offset; public: inline far_pointer(unsigned short argSegmentSelector, T* argOffset) :segmentSelector(argSegmentSelector), offset(argOffset) {} template <class Tp> inline operator far_pointer<Tp>() { return far_pointer<Tp>(segmentSelector, (Tp*) offset); } inline T* getOffset() { return offset; } inline unsigned short getSegmentselector() { return segmentSelector; } inline T operator*(void) { T item; __asm__ ( " .intel_syntax noprefix; \n mov gs, %1; \n mov %0, gs:[%2]; \n " :"=q"(item) :"r"(this->segmentSelector), "g"(this->offset) ); return item; } inline far_pointer<T>& operator++(void) { offset++; return *this; } inline far_pointer<T>& operator--(void) { offset--; return *this; } inline size_t operator-(far_pointer<T> const& subs) { return offset-subs.offset; } inline far_pointer operator+(int argDecal) { return far_pointer(segmentSelector, offset + argDecal); } inline far_pointer operator-(int argDecal) { return far_pointer(segmentSelector, offset - argDecal); } inline far_pointer operator+(unsigned argDecal) { return far_pointer(segmentSelector, offset + argDecal); } inline far_pointer operator-(unsigned argDecal) { return far_pointer(segmentSelector, offset - argDecal); } inline void operator+=(unsigned argDecal) { offset += argDecal; } inline void operator-=(unsigned argDecal) { offset -= argDecal; } inline void operator+=(int argDecal) { offset += argDecal; } inline void operator-=(int argDecal) { offset -= argDecal; } inline far_pointer operator+(long argDecal) { return far_pointer(segmentSelector, offset + argDecal); } inline far_pointer operator-(long argDecal) { return far_pointer(segmentSelector, offset - argDecal); } inline far_pointer operator+(unsigned long argDecal) { return far_pointer(segmentSelector, offset + argDecal); } inline far_pointer operator-(unsigned long argDecal) { return far_pointer(segmentSelector, offset - argDecal); } inline void operator+=(unsigned long argDecal) { offset += argDecal; } inline void operator-=(unsigned long argDecal) { offset -= argDecal; } inline void operator+=(long argDecal) { offset += argDecal; } inline void operator-=(long argDecal) { offset -= argDecal; } inline bool operator<(far_pointer<T> const& ptr) { return offset < ptr.offset; } inline bool operator>(far_pointer<T> const& ptr) { return offset > ptr.offset; } inline bool operator<=(far_pointer<T> const& ptr) { return offset <= ptr.offset; } inline bool operator>=(far_pointer<T> const& ptr) { return offset >= ptr.offset; } inline bool operator!=(far_pointer<T> const& ptr) { return offset != ptr.offset || segmentSelector != ptr.segmentSelector; } inline bool operator==(far_pointer<T> const& ptr) { return offset == ptr.offset && segmentSelector == ptr.segmentSelector; } static const far_pointer<T> NULL_FAR_POINTER; }; template <class T> const far_pointer<T> far_pointer<T>::NULL_FAR_POINTER(0,(T*) 0); # 2 "main.cpp" 2 char u; void toto(far_pointer<unsigned char> pt) { u = *pt; } int main(int argc, char **argv) { unsigned short dataSeg = 0; asm ( " .intel_syntax noprefix; \n mov %0, cs; \n " : "=r"(dataSeg) ); far_pointer<unsigned char> pt(dataSeg, (unsigned char*) &main); toto(pt); } -------------------------------------------------------------------------------- COLLECT_GCC_OPTIONS='-c' '-masm=intel' '-save-temps' '-v' '-O1' '-o' './Release/main.o' '-I.' '-shared-libgcc' '-mtune=i386' '-march=i386' c:/mingw/bin/../libexec/gcc/mingw32/4.5.0/cc1plus.exe -fpreprocessed main.ii -quiet -dumpbase main.cpp -masm=intel -mtune=i386 -march=i386 -auxbase-strip ./Release/main.o -O1 -version -o main.s GNU C++ (GCC) version 4.5.0 (mingw32) compiled by GNU C version 4.5.0, GMP version 5.0.1, MPFR version 2.4.1, MPC version 0.8.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C++ (GCC) version 4.5.0 (mingw32) compiled by GNU C version 4.5.0, GMP version 5.0.1, MPFR version 2.4.1, MPC version 0.8.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 639ec8dd7c9bc03705b4424f5e166212 COLLECT_GCC_OPTIONS='-c' '-masm=intel' '-save-temps' '-v' '-O1' '-o' './Release/main.o' '-I.' '-shared-libgcc' '-mtune=i386' '-march=i386' c:/mingw/bin/../lib/gcc/mingw32/4.5.0/../../../../mingw32/bin/as.exe -o ./Release/main.o main.s main.s: Messages de l'assembleur: main.s:22: ERREUR: `al' not allowed with `movl' mingw32-make.exe[1]: *** [Release/main.o] Error 1 "mingw32-make.exe": *** [All] Error 2 The origin is the inlining of T operator*(void) in toto(far_pointer<unsigned char> pt) in main.ii. This output is the same whatever optimization level but with -g. In this last case, there is no error. A similar ouput is observable on Linux with g++-4.5 (Ubuntu 4.5.0-3ubuntu1) 4.5.1 20100519 (prerelease) with the same command-line. The error message differs, nevertheless: main.s: Assembler messages: main.s:31: Error: operand type mismatch for `movsbl' main.s:32: Error: no such instruction: `movl %eax,8(%esp)' main.s:33: Error: no such instruction: `movl $.LC0,4(%esp)' main.s:34: Error: no such instruction: `movl $1,(%esp)' main.s:36: Error: no such instruction: `movl $0,%eax' -- Summary: [Extended inline asm] wrong assembly generation on IA32 Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: dg dot recrutement31 at gmail dot com GCC host triplet: Windows Vista 32 bit and Linux 32 bit GCC target triplet: i386 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44288