The "IT DOESN'T WORK!" thread

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

Rysto
Posts: 1459
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Rysto » Sat Feb 02, 2013 4:10 pm UTC

Protip: java.util.Set.toString() returns exactly the same string representation for a set containing no elements and a set containing an empty string. Remember this before you go insane half-convincing yourself that Set.equals() is broken for comparing empty sets.

User avatar
tastelikecoke
Posts: 1208
Joined: Mon Feb 01, 2010 7:58 am UTC
Location: Antipode of Brazil
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby tastelikecoke » Thu Feb 07, 2013 1:16 pm UTC

phlip wrote:Actually, my real rule of thumb is: don't use things like Scanner (similarly the scanf family in C, and cin.operator>> in C++) because they so rarely do what you want.

scanf and cin>> are much more convenient if you're assuming correct input. (Java, not so much. BufferedReader + string split() + Integer.parseInt works better for me) Their behavior is fairly determinate: it takes in the stream any whitespace, then any non-whitespace and stops to the boundary of non-whitespace and whitespace. So if layout is critical, you can mix the scanf, getc, and fgets if you're careful.

User avatar
phlip
Restorer of Worlds
Posts: 7543
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Thu Feb 07, 2013 11:23 pm UTC

Sure, but when was the last time you could assume correct input for user-entered data? Sure, if you're reading from some machine-generated file with a fixed format, use whatever tools make it easiest to read... but when you're doing the interactive-prompt-and-response thing with a user at a TTY, you want to be using something that reads by line (fgets, istream::getline, BufferedReader.readLine, etc), not something that splits by tokens, and can have what the user typed for one prompt be read as a response to a different prompt.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

gametaku
Posts: 148
Joined: Tue Dec 30, 2008 2:21 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby gametaku » Mon Feb 18, 2013 6:55 pm UTC

The following code should print out '-3' four times. Once for the data section, and three more times for registers. It works for the data section but not registers. Instead I get 253, which means that the registers are being treated as unsigned.

Code: Select all

.586
.model flat, c
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib

printf    PROTO arg1:Ptr Byte, printlist: VARARG
 .STACK 100h
.data
fmtlist   BYTE   "%s, %d", 0Ah,0
string_1  BYTE   "The result is", 0

disAllFrm BYTE "%s %i, %i, %i, %i",13,10,0
disAll    BYTE   "Test, EAX, AX, AL", 13,10,0
tv dd -3

.code
start:
mov EAX, 0
mov AL, -3

;This line should print out:
; Test, EAX, AX, AL
; -3, -3, -3, -3
 INVOKE    printf, ADDR disAllFrm, addr disAll, tv, eax, ax, al
 
 invoke ExitProcess, 0
end start

User avatar
chridd
Has a vermicelli title
Posts: 765
Joined: Tue Aug 19, 2008 10:07 am UTC
Location: ...Earth, I guess?
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby chridd » Mon Feb 18, 2013 8:12 pm UTC

gametaku wrote:

Code: Select all

mov EAX, 0
mov AL, -3
EAX isn't -3 after these lines. The low byte of EAX (AL) is -3, and the other bytes I believe remain 0 (are unchanged). Wikipedia says that MOVSX will sign-extend the result, so maybe that's what you're looking for.

I also notice that the format string doesn't specify sizes for the shorter arguments, so you might need to fix that, too.
~ chri d. d. /tʃɹɪ.di.di/ (Phonotactics, schmphonotactics) · they (for now, at least) · Forum game scores
mittfh wrote:I wish this post was very quotable...
flicky1991 wrote:In both cases the quote is "I'm being quoted too much!"

gametaku
Posts: 148
Joined: Tue Dec 30, 2008 2:21 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby gametaku » Mon Feb 18, 2013 8:49 pm UTC

chridd wrote:
gametaku wrote:

Code: Select all

mov EAX, 0
mov AL, -3
EAX isn't -3 after these lines. The low byte of EAX (AL) is -3, and the other bytes I believe remain 0 (are unchanged). Wikipedia says that MOVSX will sign-extend the result, so maybe that's what you're looking for.

I also notice that the format string doesn't specify sizes for the shorter arguments, so you might need to fix that, too.


I made the following changes which should fix the problem of having not specified the size arguments in the format string, and dealing with register sizes.

Code: Select all

disAllFrm BYTE "%s %i, %d, %hd, %hhd",13,10,0
;....

start:
mov EAX, 0
mov AL, -3
INVOKE    printf, ADDR disAllFrm, addr disAll, tv, EAX, AX, AL
 
mov EAX, 0
mov AX, -3
INVOKE    printf, ADDR disAllFrm, addr disAll, tv, EAX, AX, AL
 
mov EAX, 0
mov EAX, -3
INVOKE    printf, ADDR disAllFrm, addr disAll, tv, EAX, AX, AL


and get:
Test, EAX, AX, AL
-3, 253, 253, 253
Test, EAX, AX, AL
-3, 253, 253, 253
Test, EAX, AX, AL
-3, -65283, 253, 253

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Mon Feb 18, 2013 10:17 pm UTC

I wrote a quick little test along the following lines to obtain the same problem.

Code: Select all

.model flat,c
.stack
.data
printf    PROTO arg1:Ptr Byte, printlist: VARARG
msg db "%hd ",10,0
.code

includelib MSVCRT
extrn exit:near

main proc
   xor eax,eax
   mov al,-3
   movsx eax,al
   invoke printf, addr msg, al
   call exit
main endp
end main


dissassembly:

Code: Select all

   xor eax,eax
00AE1041 33 C0                xor         eax,eax 
   mov al,-3
00AE1043 B0 FD                mov         al,0FDh 
   movsx eax,al
00AE1045 0F BE C0             movsx       eax,al 
   invoke printf, addr msg, al
00AE1048 66 6A 00             push        0 
00AE104B 66 0F B6 C0          movzx       ax,al 
00AE104F 66 50                push        ax 
00AE1051 68 00 40 AE 00       push        offset msg (0AE4000h) 
00AE1056 E8 23 00 00 00       call        printf (0AE107Eh) 
00AE105B 83 C4 08             add         esp,8 


In particular, notice the "movzx ax,al" line?
al cannot be pushed onto the stack and so ax is instead (after the movzx operation).
Why the movzx? I haven't a clue.

Indeed, looking at the disassembly for your code

Code: Select all

    INVOKE    printf, ADDR disAllFrm, addr disAll, tv, eax, ax, al
00DA101A 66 6A 00             push        0 
00DA101D 66 0F B6 C0          movzx       ax,al 
00DA1021 66 50                push        ax 
00DA1023 66 6A 00             push        0 
00DA1026 66 50                push        ax 
00DA1028 50                   push        eax 
00DA1029 FF 35 31 40 DA 00    push        dword ptr [tv (0DA4031h)] 
00DA102F 68 1D 40 DA 00       push        offset disAll (0DA401Dh) 
00DA1034 68 06 40 DA 00       push        offset disAllFrm (0DA4006h) 
00DA1039 E8 3C 00 00 00       call        printf (0DA107Ah) 
00DA103E 83 C4 18             add         esp,18h 


The high-byte of ax gets zeroed before ax or eax are pushed, resulting in the weird values.
Don't try inserting al and your code works as expected.

Edit:
I guess the movzx is done to ensure AH doesn't contain garbage when you try to manipulate AX as AH. A similar problem would occur if the instruction was "movsx ax,ah".
I suppose the lesson is to not try to do things your processor doesn't support. ;)
Image

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby jareds » Mon Feb 18, 2013 10:35 pm UTC

The documentation for INVOKE says:
If an argument passed by INVOKE is smaller than the type specified in the PROTO statement, MASM does a type conversion. It widens the argument in the PROTO statement to match that in the INVOKE statement (for example, SBYTE to SWORD). These types of conversions use the AX and DX registers on the 8086 and 8088 and the EAX and EDX registers on the 80386/80486. Because these registers are effectively overwritten, you should take care to avoid using these registers to pass arguments.

The calling convention for varargs on x86 is that integer arguments smaller than 32 bits are passed as 32 bits on the stack. MASM thus widens your AL argument, trashing EAX as warned above for the rest of your arguments (right-to-left). If you used a different register MASM would still presumably chose to zero-extend it rather than sign-extend. I don't know enough about MASM to know if you can tell it to sign extend it. You could just sign-extend it yourself and pass the 32-bit register you've extended it into, since it has to get passed as 32 bits anyway.

gametaku
Posts: 148
Joined: Tue Dec 30, 2008 2:21 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby gametaku » Tue Feb 19, 2013 5:09 pm UTC

Xenomortis wrote:I wrote a quick little test along the following lines to obtain the same problem.

Code: Select all

.model flat,c
.stack
.data
printf    PROTO arg1:Ptr Byte, printlist: VARARG
msg db "%hd ",10,0
.code

includelib MSVCRT
extrn exit:near

main proc
   xor eax,eax
   mov al,-3
   movsx eax,al
   invoke printf, addr msg, al
   call exit
main endp
end main


dissassembly:

Code: Select all

   xor eax,eax
00AE1041 33 C0                xor         eax,eax 
   mov al,-3
00AE1043 B0 FD                mov         al,0FDh 
   movsx eax,al
00AE1045 0F BE C0             movsx       eax,al 
   invoke printf, addr msg, al
00AE1048 66 6A 00             push        0 
00AE104B 66 0F B6 C0          movzx       ax,al 
00AE104F 66 50                push        ax 
00AE1051 68 00 40 AE 00       push        offset msg (0AE4000h) 
00AE1056 E8 23 00 00 00       call        printf (0AE107Eh) 
00AE105B 83 C4 08             add         esp,8 


In particular, notice the "movzx ax,al" line?
al cannot be pushed onto the stack and so ax is instead (after the movzx operation).
Why the movzx? I haven't a clue.

Indeed, looking at the disassembly for your code

Code: Select all

    INVOKE    printf, ADDR disAllFrm, addr disAll, tv, eax, ax, al
00DA101A 66 6A 00             push        0 
00DA101D 66 0F B6 C0          movzx       ax,al 
00DA1021 66 50                push        ax 
00DA1023 66 6A 00             push        0 
00DA1026 66 50                push        ax 
00DA1028 50                   push        eax 
00DA1029 FF 35 31 40 DA 00    push        dword ptr [tv (0DA4031h)] 
00DA102F 68 1D 40 DA 00       push        offset disAll (0DA401Dh) 
00DA1034 68 06 40 DA 00       push        offset disAllFrm (0DA4006h) 
00DA1039 E8 3C 00 00 00       call        printf (0DA107Ah) 
00DA103E 83 C4 18             add         esp,18h 


The high-byte of ax gets zeroed before ax or eax are pushed, resulting in the weird values.
Don't try inserting al and your code works as expected.

Edit:
I guess the movzx is done to ensure AH doesn't contain garbage when you try to manipulate AX as AH. A similar problem would occur if the instruction was "movsx ax,ah".
I suppose the lesson is to not try to do things your processor doesn't support. ;)


Changing the function to take 32 bit values seemed to solve the problem. Thanks.

User avatar
LID919
Posts: 27
Joined: Sun Feb 17, 2013 10:21 pm UTC
Location: Colorado.

Re: The "IT DOESN'T WORK!" thread

Postby LID919 » Wed Feb 20, 2013 7:45 pm UTC

Greetings everyone.

I've been working on this program for some amount of time now. I used to have a ton of bugs with it, but then I scrapped it and rewrote it from source, and most of them went away. Now, I have only one bug left.

I'm compiling in visual studio c++ 2010 express, and I get the following error, listed in multiple places:

7 IntelliSense: more than one operator "<<" matches these operands: c:\users\ian\my programs\program directories\games\blackjack simulator\blackjacksimulator\blackjacksimulator\blackjacksimulatorfunctions.cpp 511


that, and the same thing for ">>":

Error 2 error C2666: 'operator >>' : 2 overloads have similar conversions c:\users\ian\my programs\program directories\games\blackjack simulator\blackjacksimulator\blackjacksimulator\blackjacksimulatorfunctions.cpp 145


All of the errors say that same thing.

Now, the problem is in the fstream functions (the save function and the load function) of my blackjackSimulatorFunctions.cpp file.

If it underlined the problem referencing printing one of my classes, I would immeditely look there, but that is where the odd part happens:

My classes use the "<<" and ">>" operators just fine, it is default data types (int, char, float) that glitch.

I've looked and looked and cannot find the problem, can anyone see if they can see something I can't?

Here is a link the source code.//problem solved, link taken down

Thanks in advance to all who respond.
Last edited by LID919 on Wed Feb 20, 2013 9:49 pm UTC, edited 4 times in total.
Day 3:
"Alright, just finish up those class implementations, and we can get this working."
Day 5:
"Ok, forget cleaning up the GUI, lets just find out why it keeps crashing after the user inputs that option."
Day 7:
"It actually compiles? Great! Ship it!"

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Wed Feb 20, 2013 8:14 pm UTC

Make your 1 argument constructors explicit.

Oh, and when asking for help about an error, past the entire error. I might be able to read your mind, but I shouldn't have to. There should be a pile of junk that says which are the two candidate operator>>s, is there not?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
LID919
Posts: 27
Joined: Sun Feb 17, 2013 10:21 pm UTC
Location: Colorado.

Re: The "IT DOESN'T WORK!" thread

Postby LID919 » Wed Feb 20, 2013 9:50 pm UTC

That solved the problem. Thank you.
Day 3:
"Alright, just finish up those class implementations, and we can get this working."
Day 5:
"Ok, forget cleaning up the GUI, lets just find out why it keeps crashing after the user inputs that option."
Day 7:
"It actually compiles? Great! Ship it!"

User avatar
LID919
Posts: 27
Joined: Sun Feb 17, 2013 10:21 pm UTC
Location: Colorado.

Re: The "IT DOESN'T WORK!" thread

Postby LID919 » Fri Feb 22, 2013 8:54 pm UTC

Sorry to double post, but here we are with the last bug in the program I previously asked about.


I am experiencing linking errors in my classes from what I can gather, but I was unable to hunt them down. Excuse my blindness if there is an obvious one.

Here is the error list itself:
Spoiler:
Error 8 error LNK1120: 3 unresolved externals C:\Users\Ian\My Programs\Program Directories\Games\BlackJack Simulator\blackjackSimulator\Debug\blackjackSimulator.exe
Error 7 error LNK2001: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Card &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAVCard@@@Z) C:\Users\Ian\My Programs\Program Directories\Games\BlackJack Simulator\blackjackSimulator\blackjackSimulator\Hand.obj
Error 6 error LNK2019: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Card &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAVCard@@@Z) referenced in function "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Deck &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAVDeck@@@Z) C:\Users\Ian\My Programs\Program Directories\Games\BlackJack Simulator\blackjackSimulator\blackjackSimulator\Deck.obj
Error 5 error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl convertToSuitString(char)" (?convertToSuitString@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@D@Z) referenced in function "public: void __thiscall Card::setSuit(char)" (?setSuit@Card@@QAEXD@Z) C:\Users\Ian\My Programs\Program Directories\Games\BlackJack Simulator\blackjackSimulator\blackjackSimulator\Card.obj
Error 4 error LNK2019: unresolved external symbol "void __cdecl loadGame(float *,class Hand *,class Hand *,int,class Deck *,bool *,char const *)" (?loadGame@@YAXPAMPAVHand@@1HPAVDeck@@PA_NPBD@Z) referenced in function _main C:\Users\Ian\My Programs\Program Directories\Games\BlackJack Simulator\blackjackSimulator\blackjackSimulator\blackjackSimulator.obj


And here is a link to the source code.//Link taken down, problem solved

Thanks again to all who reply.


//EDIT: I am compiling in Microsoft Visual Studio C++ 2010 express.
Last edited by LID919 on Fri Feb 22, 2013 10:56 pm UTC, edited 2 times in total.
Day 3:
"Alright, just finish up those class implementations, and we can get this working."
Day 5:
"Ok, forget cleaning up the GUI, lets just find out why it keeps crashing after the user inputs that option."
Day 7:
"It actually compiles? Great! Ship it!"

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Fri Feb 22, 2013 9:48 pm UTC

Include your compiler command line. Are you compiling every .cpp file?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
LID919
Posts: 27
Joined: Sun Feb 17, 2013 10:21 pm UTC
Location: Colorado.

Re: The "IT DOESN'T WORK!" thread

Postby LID919 » Fri Feb 22, 2013 9:57 pm UTC

I'm compiling in microsoft visual studio c++ 2010 express. It doesn't compile by a command line, there is a compile button that compiles all the files listed as included in project (and all the cpp files are there).

Call me a wimp for not using UNIX if you must, but hey, this makes for faster programming (usually).
Day 3:
"Alright, just finish up those class implementations, and we can get this working."
Day 5:
"Ok, forget cleaning up the GUI, lets just find out why it keeps crashing after the user inputs that option."
Day 7:
"It actually compiles? Great! Ship it!"

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Fri Feb 22, 2013 10:08 pm UTC

There is still a compiler command line almost certainly. It is just hidden behind some gui widget somewhere. You should find it: it is in the vcproj, and you might be able to find it under right-click project properties. (I haven't used express)

Then check the signatures of your operator>>s and make sure they match in the .h and .cpp file.
Last edited by Yakk on Fri Feb 22, 2013 10:50 pm UTC, edited 1 time in total.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
LID919
Posts: 27
Joined: Sun Feb 17, 2013 10:21 pm UTC
Location: Colorado.

Re: The "IT DOESN'T WORK!" thread

Postby LID919 » Fri Feb 22, 2013 10:14 pm UTC

They are a perfect match in both the .h and .cpp files of each class.
Day 3:
"Alright, just finish up those class implementations, and we can get this working."
Day 5:
"Ok, forget cleaning up the GUI, lets just find out why it keeps crashing after the user inputs that option."
Day 7:
"It actually compiles? Great! Ship it!"

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Fri Feb 22, 2013 10:48 pm UTC

Ya, no:

Code: Select all

.h file:
std::istream& operator >> (std::istream& I, Card& c);
.cpp file:
std::istream& operator >> (std::istream I, Card& c)

It wasn't plugged in. :p
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
LID919
Posts: 27
Joined: Sun Feb 17, 2013 10:21 pm UTC
Location: Colorado.

Re: The "IT DOESN'T WORK!" thread

Postby LID919 » Fri Feb 22, 2013 10:57 pm UTC

That was it. Thank you for your help. I apologise for my blindness and insisting that the two were identical. I thought I had checked thouroughly enough.
Day 3:
"Alright, just finish up those class implementations, and we can get this working."
Day 5:
"Ok, forget cleaning up the GUI, lets just find out why it keeps crashing after the user inputs that option."
Day 7:
"It actually compiles? Great! Ship it!"

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Sat Feb 23, 2013 1:24 am UTC

The first rule of programming is "it isn't plugged in".

There is some brain dead, simple thing you are missing, almost always. You aren't running the code you think you are running. You didn't check that your array is large enough for your data. Etc etc.

Programming is a huge pile of brain dead, simple things, arranged together into a monolith of amazing complexity that boggles the mind.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

wurlitzer153
Posts: 68
Joined: Mon Dec 10, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby wurlitzer153 » Sat Feb 23, 2013 3:51 am UTC

Ain't that the truth...

Not long ago I spent a WEEK figuring out why a very simple byte swap routine was spitting out too many bytes. Turned out I opened the output file (using fopen()) with the 'w' flag instead of the "bw" flag and Win was replacing \n (in a binary file) with crlf. But I was sure I had used the correct flag....

Mind you, I was also opening text files for hex dumping. So that was simply not paying attention to copy and paste.

Protoform
Posts: 43
Joined: Sun Dec 30, 2012 1:09 pm UTC
Location: The Nether

Re: The "IT DOESN'T WORK!" thread

Postby Protoform » Fri Mar 01, 2013 11:37 pm UTC

I've recently taken up my hobby of messing around with shellcode again, and quickly found out that doing that in GDB on the x86_64 is *much* more frustrating. AT&T style doesn't help. (Yes, yes, I know of the Intel parameter thingy.)

EvanED
Posts: 4324
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Sat Mar 02, 2013 2:46 am UTC

Protoform wrote:I've recently taken up my hobby of messing around with shellcode again, and quickly found out that doing that in GDB on the x86_64 is *much* more frustrating.
...than what? x86? In what way?

(Also yes, AT&T syntax is an abomination against all that is holy and right. :-))

User avatar
Negrebskoh
Posts: 139
Joined: Fri Mar 01, 2013 11:49 pm UTC
Location: The Netherlands

Re: The "IT DOESN'T WORK!" thread

Postby Negrebskoh » Wed Mar 06, 2013 11:22 am UTC

EvanED wrote:
Protoform wrote:I've recently taken up my hobby of messing around with shellcode again, and quickly found out that doing that in GDB on the x86_64 is *much* more frustrating.
...than what? x86? In what way?


I've reversed some minimal x86_64 and x86 code myself, and in my experience the 64 bit kind just adds all sorts of extra stuff that makes it even harder to understand, though that may just be GDB.



No argument there. ;)

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Wed Mar 06, 2013 11:30 am UTC

As I understand, x64 compilers have a tendency to be much more aggressive when it comes to be optimisation.
Image

User avatar
Negrebskoh
Posts: 139
Joined: Fri Mar 01, 2013 11:49 pm UTC
Location: The Netherlands

Re: The "IT DOESN'T WORK!" thread

Postby Negrebskoh » Wed Mar 06, 2013 11:37 am UTC

Just wrote a simple piece of code to see what the differences would be, but the differences turn out not to actually be that major. Of course, GDBs output is still unreadable without setting the disassembly flavor to Intel, but it's not as bad as I remember (which means I probably remember the wrong thing).

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Wed Mar 06, 2013 11:45 am UTC

How simple was simple? Try writing a bit more; pass arguments into a couple of functions and do a small amount of work on them.
Image

User avatar
Negrebskoh
Posts: 139
Joined: Fri Mar 01, 2013 11:49 pm UTC
Location: The Netherlands

Re: The "IT DOESN'T WORK!" thread

Postby Negrebskoh » Wed Mar 06, 2013 2:52 pm UTC

Xenomortis wrote:How simple was simple? Try writing a bit more; pass arguments into a couple of functions and do a small amount of work on them.


Extremely simple:

Code: Select all

#include <stdio.h>

int main(void) {
   int i, n;

   n = 0;
   for (i=0; i<100; i++) {
      n += i;
   }

   fprintf(stdout, "%d\n", n);

   return 0;
}


I might test a larger program later, and also mess around a bit with those optimization settings in GCC. First, grocery shopping.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Sat Jun 01, 2013 12:20 am UTC

Why can I not find the command line arguments that get passed to my Windows assembler program?
Various sites claim they can find them on the stack, but I cannot and that makes me sad. :cry:
I think these others are lying.

Relevant bits.

Code: Select all

.data
    msg    byte    'test is: %s',10,0
.code
main:
    mov    ebp, esp
    sub    esp,4   

    mov     eax, dword ptr [ebp+8]
    push    dword ptr [eax+4] ;I've been shooting in the dark, hence the random additions
    push    offset msg
    call    printf ;prints garbage/nothing

...
rest of program



I'll step through the disassembly for a C program later... it's late and I'm tired.

(The API function GetCommandLine works, but I'd rather avoid it, unless the alternatives proves no better - it returns the entire command line input as a string)
Image

User avatar
thoughtfully
Posts: 2243
Joined: Thu Nov 01, 2007 12:25 am UTC
Location: Minneapolis, MN
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby thoughtfully » Sat Jun 01, 2013 1:14 am UTC

I once wrote a parser for GetCommandLine output, since burrowing around inside gcc source didn't appeal to me. I needed it becasue only windowed applications get a nice argc/argv setup, not terminal apps that run windowless. It was an unholy mess of terse nested loops using pointers everywhere. It supported quotes, too. It worked pretty well, and I verified most of the corner cases. I'll never show it to anyone, though!

Maybe some day I'll set up proper unit tests and post it at one of the legion of sites for evil C code. Be good for my mad scientist cred.

Heh, it occurs to me that terse pointer code is probably easy to translate to assembler.
Image
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
-- Antoine de Saint-Exupery

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Sat Jun 01, 2013 5:31 pm UTC

Code: Select all

int main(int argc, char* argv[])
{
    char** a = argv;
    char* b;
    int testebp,testesp;
    _asm{
        lea eax, argv
        mov a, eax
        lea eax, argc
        mov b, eax
        mov testebp, ebp
        mov testesp, esp
    }
    printf("argv: %d\nargc: %d\nebp : %d\nesp : %d",a,b,testebp,testesp);
    return 0;
}

Prints:

Code: Select all

argv: [X + 12]
argc: [X + 8]
ebp: X
esp: [X - 16]

So I have no idea what I was doing wrong, but at least I know that the argv pointer is on the stack at the usual place.
Presumably I'm just dereferencing something wrong. I guess the next step is to see what's actually at [argv].

Edit:
Appended this

Code: Select all

    _asm{
        mov eax, argv
        mov ebx, [eax]
        mov eax, [eax+4]
        mov a, eax
        mov b, ebx
    }
    printf("%s\n%s\n",b,a);

Prints

Code: Select all

C:\scratch\args\argtest\Release\argtest.exe
testarg

i.e. the (verbose, courtesy of Visual Studio) executable path and the first argument.

So all is as it should be.
Now I examine my assembler code.
Image

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Sat Jun 01, 2013 10:48 pm UTC

Eugh... It's definitely not there on my assembler program's stack, whatever my C++ program suggests.
Presumably it's some trickery being pulled by the compiler/linker that gets these arguments onto the stack.
From what I can gather, Windows used to (I don't know if it still does) put the entire command line into a separate segment that cannot be accessed in protected mode.
And so Windows expects you to use the GetCommandLineX function and parse through it yourself.

Ah well, this program has precisely one purpose and the input is tightly controlled, so I can be lazy.
Image

User avatar
thoughtfully
Posts: 2243
Joined: Thu Nov 01, 2007 12:25 am UTC
Location: Minneapolis, MN
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby thoughtfully » Sun Jun 02, 2013 1:21 am UTC

Back In The Day, DOS and I imagine the pre-win2k versions of windows, each program had a program segment prefix. .COM programs, anyway. Argghh, that was a long time ago. The .COM programs started at address 0x100 and there was fun metadata in the preceeding 256 bytes. The command line started at 0x80. I never got the hang of .EXE programs, at least not at the low level. Soon enough I was happy in LinuxLand, and didn't really have much to to do with assembler afterwards.
Image
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
-- Antoine de Saint-Exupery

EvanED
Posts: 4324
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Sun Jun 02, 2013 2:07 am UTC

Xenomortis wrote:Eugh... It's definitely not there on my assembler program's stack, whatever my C++ program suggests.
Presumably it's some trickery being pulled by the compiler/linker that gets these arguments onto the stack.
From what I know, I'd guess that it's the C runtime that does that. main() isn't the entry point to your program after all -- even in the C world, it needs to do initialization of globals and such. So presumably the C runtime, after doing that, will parse the command line into separate arguments (natively you get the exact command line) and then call main() with those.

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby jareds » Sun Jun 02, 2013 4:33 am UTC

Just to expand on that a bit, your actual problem is presumably that you're building your assembly version of the program in such a way that the entry point is your "main" function. For a console application linked with the Visual Studio C run-time (MSVCRT), you need the entry point to be mainCRTStartup (or wmainCRTStartup for Unicode), which will call main (or wmain) after parsing the command line that it gets from GetCommandLine and doing other initialization. For a console application, you also want to make sure that the executable is set to the "console" subsystem type, which controls how Windows starts the application.

Please note that it's not reasonable to call C library functions such as printf if you are not running the CRT startup, as it's perfectly legitimate for the startup code to be doing important initialization for the C I/O functions. (I don't know about MSVCRT specifically, but in general it's bad to skip all the C library startup code and then use the C library.)

You can write a program that doesn't use the CRT at all, just the Win32 API. For example, I believe you would use GetStdHandle and ReadFile/WriteFile for standard I/O.

You would also definitely use GetCommandLine to get the command line if you don't use the CRT. It is not reasonable to expect to pull it directly out of memory somewhere: since Windows is a modern, memory-protected OS, you must either use system calls (Win32) or library calls that rely on the system calls (the CRT)--there is no alternative to directly or indirectly using the interfaces provided by a memory-protected OS. (It is also possible that some Win32 functions are also higher level functions that rely on undocumented system calls--again, I'm not an expert on Windows internals.)

At the OS level in Windows, the command line is not divided into separate arguments. See for example the CreateProcess function. Any such division is implemented by the MSVCRT wrapper code by parsing.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Sun Jun 02, 2013 9:48 am UTC

thoughtfully wrote:Back In The Day, DOS and I imagine the pre-win2k versions of windows, each program had a program segment prefix. .COM programs, anyway. Argghh, that was a long time ago. The .COM programs started at address 0x100 and there was fun metadata in the preceeding 256 bytes. The command line started at 0x80.
EvanED wrote:From what I know, I'd guess that it's the C runtime that does that. main() isn't the entry point to your program after all -- even in the C world, it needs to do initialization of globals and such. So presumably the C runtime, after doing that, will parse the command line into separate arguments (natively you get the exact command line) and then call main() with those.

This was essentially what I discovered.

jareds wrote:Please note that it's not reasonable to call C library functions such as printf if you are not running the CRT startup, as it's perfectly legitimate for the startup code to be doing important initialization for the C I/O functions. (I don't know about MSVCRT specifically, but in general it's bad to skip all the C library startup code and then use the C library.)

You can write a program that doesn't use the CRT at all, just the Win32 API. For example, I believe you would use GetStdHandle and ReadFile/WriteFile for standard I/O.

The printf call wasn't originally part of the main program. In fact, the program doesn't ever need to write to the console.
I just used printf for debugging purposes because it was quicker to set up than WriteConsole, and since it worked, I never gave it second thought.
The rest of the program just uses the Win32 API.

jareds wrote:At the OS level in Windows, the command line is not divided into separate arguments. See for example the CreateProcess function. Any such division is implemented by the MSVCRT wrapper code by parsing.

Found that out too.


Thanks for the exposition.
Image

User avatar
phlip
Restorer of Worlds
Posts: 7543
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Fri Jun 28, 2013 2:09 am UTC

Today, step by step:
Attempt to connect to web service via unfamiliar Java WSDL library.
Request fails with non-useful error message from server.
Copy-paste out request headers and body via Fiddler, for tinkering purposes.
Connect to server directly with openssl and paste in request, unchanged.
Request succeeds.

Wat.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Xenomortis
Not actually a special flower.
Posts: 1397
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xenomortis » Fri Jun 28, 2013 7:47 am UTC

Cosmic Rays.
Image

Princess Marzipan
Posts: 7717
Joined: Sun May 27, 2007 5:28 am UTC
Location: neither a road, nor an island

Re: The "IT DOESN'T WORK!" thread

Postby Princess Marzipan » Sun Jul 07, 2013 8:12 pm UTC

I'm working on a personal project in python. I have some classes that inherit some basic functionality from a superclass which inherits object. The superclass has an __init__ with steps relevant to all subclasses; the subclasses have their own __init__s which call super() on the superclass __init__.

I never actually create an object from the superclass; I'm only using instances of the subclasses. I have a method in the superclass that alters a list attribute. In testing what I've built so far, I am creating three instances of one of the subclasses, and calling that list-altering method once for each of them:

Code: Select all

sub1 = Sub(...)
sub1.liststuff([a,b]
sub2 = Sub(...)
sub2.liststuff[c,d]
sub3 = Sub(...)
sub3.liststuff([e,f])

After this, sub1.list, sub2.list, and sub3.list are *identical*; all are [a,b,c,d,e,f].

I...what? Halps? Glad to explain further if necessary.
"It's Saturday night. I've got no date, a two-liter of Shasta, and my all-Rush mixtape. Let's rock!"
"I am just about to be brilliant!"
General_Norris, on feminism, wrote:If you lose your six Pokémon, you lost.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5963
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: The "IT DOESN'T WORK!" thread

Postby jestingrabbit » Sun Jul 07, 2013 8:56 pm UTC

When you say objects are identical in python, I would normally take that to mean the id(obj1) == id(obj2). Is this the case?

You might need to post the code for "liststuff" at some point.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 7 guests